From f6418b17d89f0ef18c8bce670c6247c26d86540f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:34:44 -0500 Subject: [PATCH 001/398] move orignial cross file to new --- packages/cross_file/{ => cross_file}/AUTHORS | 0 packages/cross_file/{ => cross_file}/CHANGELOG.md | 0 packages/cross_file/{ => cross_file}/LICENSE | 0 packages/cross_file/{ => cross_file}/README.md | 0 packages/cross_file/{ => cross_file}/dart_test.yaml | 0 packages/cross_file/{ => cross_file}/example/assets/hello.txt | 0 packages/cross_file/{ => cross_file}/example/dart_test.yaml | 0 .../cross_file/{ => cross_file}/example/lib/readme_excerpts.dart | 0 packages/cross_file/{ => cross_file}/example/pubspec.yaml | 0 .../{ => cross_file}/example/test/readme_excerpts_test.dart | 0 packages/cross_file/{ => cross_file}/lib/cross_file.dart | 0 packages/cross_file/{ => cross_file}/lib/src/types/base.dart | 0 packages/cross_file/{ => cross_file}/lib/src/types/html.dart | 0 packages/cross_file/{ => cross_file}/lib/src/types/interface.dart | 0 packages/cross_file/{ => cross_file}/lib/src/types/io.dart | 0 .../{ => cross_file}/lib/src/web_helpers/web_helpers.dart | 0 packages/cross_file/{ => cross_file}/lib/src/x_file.dart | 0 packages/cross_file/{ => cross_file}/pubspec.yaml | 0 packages/cross_file/{ => cross_file}/test/assets/hello.txt | 0 packages/cross_file/{ => cross_file}/test/x_file_html_test.dart | 0 packages/cross_file/{ => cross_file}/test/x_file_io_test.dart | 0 21 files changed, 0 insertions(+), 0 deletions(-) rename packages/cross_file/{ => cross_file}/AUTHORS (100%) rename packages/cross_file/{ => cross_file}/CHANGELOG.md (100%) rename packages/cross_file/{ => cross_file}/LICENSE (100%) rename packages/cross_file/{ => cross_file}/README.md (100%) rename packages/cross_file/{ => cross_file}/dart_test.yaml (100%) rename packages/cross_file/{ => cross_file}/example/assets/hello.txt (100%) rename packages/cross_file/{ => cross_file}/example/dart_test.yaml (100%) rename packages/cross_file/{ => cross_file}/example/lib/readme_excerpts.dart (100%) rename packages/cross_file/{ => cross_file}/example/pubspec.yaml (100%) rename packages/cross_file/{ => cross_file}/example/test/readme_excerpts_test.dart (100%) rename packages/cross_file/{ => cross_file}/lib/cross_file.dart (100%) rename packages/cross_file/{ => cross_file}/lib/src/types/base.dart (100%) rename packages/cross_file/{ => cross_file}/lib/src/types/html.dart (100%) rename packages/cross_file/{ => cross_file}/lib/src/types/interface.dart (100%) rename packages/cross_file/{ => cross_file}/lib/src/types/io.dart (100%) rename packages/cross_file/{ => cross_file}/lib/src/web_helpers/web_helpers.dart (100%) rename packages/cross_file/{ => cross_file}/lib/src/x_file.dart (100%) rename packages/cross_file/{ => cross_file}/pubspec.yaml (100%) rename packages/cross_file/{ => cross_file}/test/assets/hello.txt (100%) rename packages/cross_file/{ => cross_file}/test/x_file_html_test.dart (100%) rename packages/cross_file/{ => cross_file}/test/x_file_io_test.dart (100%) diff --git a/packages/cross_file/AUTHORS b/packages/cross_file/cross_file/AUTHORS similarity index 100% rename from packages/cross_file/AUTHORS rename to packages/cross_file/cross_file/AUTHORS diff --git a/packages/cross_file/CHANGELOG.md b/packages/cross_file/cross_file/CHANGELOG.md similarity index 100% rename from packages/cross_file/CHANGELOG.md rename to packages/cross_file/cross_file/CHANGELOG.md diff --git a/packages/cross_file/LICENSE b/packages/cross_file/cross_file/LICENSE similarity index 100% rename from packages/cross_file/LICENSE rename to packages/cross_file/cross_file/LICENSE diff --git a/packages/cross_file/README.md b/packages/cross_file/cross_file/README.md similarity index 100% rename from packages/cross_file/README.md rename to packages/cross_file/cross_file/README.md diff --git a/packages/cross_file/dart_test.yaml b/packages/cross_file/cross_file/dart_test.yaml similarity index 100% rename from packages/cross_file/dart_test.yaml rename to packages/cross_file/cross_file/dart_test.yaml diff --git a/packages/cross_file/example/assets/hello.txt b/packages/cross_file/cross_file/example/assets/hello.txt similarity index 100% rename from packages/cross_file/example/assets/hello.txt rename to packages/cross_file/cross_file/example/assets/hello.txt diff --git a/packages/cross_file/example/dart_test.yaml b/packages/cross_file/cross_file/example/dart_test.yaml similarity index 100% rename from packages/cross_file/example/dart_test.yaml rename to packages/cross_file/cross_file/example/dart_test.yaml diff --git a/packages/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart similarity index 100% rename from packages/cross_file/example/lib/readme_excerpts.dart rename to packages/cross_file/cross_file/example/lib/readme_excerpts.dart diff --git a/packages/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml similarity index 100% rename from packages/cross_file/example/pubspec.yaml rename to packages/cross_file/cross_file/example/pubspec.yaml diff --git a/packages/cross_file/example/test/readme_excerpts_test.dart b/packages/cross_file/cross_file/example/test/readme_excerpts_test.dart similarity index 100% rename from packages/cross_file/example/test/readme_excerpts_test.dart rename to packages/cross_file/cross_file/example/test/readme_excerpts_test.dart diff --git a/packages/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart similarity index 100% rename from packages/cross_file/lib/cross_file.dart rename to packages/cross_file/cross_file/lib/cross_file.dart diff --git a/packages/cross_file/lib/src/types/base.dart b/packages/cross_file/cross_file/lib/src/types/base.dart similarity index 100% rename from packages/cross_file/lib/src/types/base.dart rename to packages/cross_file/cross_file/lib/src/types/base.dart diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/cross_file/lib/src/types/html.dart similarity index 100% rename from packages/cross_file/lib/src/types/html.dart rename to packages/cross_file/cross_file/lib/src/types/html.dart diff --git a/packages/cross_file/lib/src/types/interface.dart b/packages/cross_file/cross_file/lib/src/types/interface.dart similarity index 100% rename from packages/cross_file/lib/src/types/interface.dart rename to packages/cross_file/cross_file/lib/src/types/interface.dart diff --git a/packages/cross_file/lib/src/types/io.dart b/packages/cross_file/cross_file/lib/src/types/io.dart similarity index 100% rename from packages/cross_file/lib/src/types/io.dart rename to packages/cross_file/cross_file/lib/src/types/io.dart diff --git a/packages/cross_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/cross_file/lib/src/web_helpers/web_helpers.dart similarity index 100% rename from packages/cross_file/lib/src/web_helpers/web_helpers.dart rename to packages/cross_file/cross_file/lib/src/web_helpers/web_helpers.dart diff --git a/packages/cross_file/lib/src/x_file.dart b/packages/cross_file/cross_file/lib/src/x_file.dart similarity index 100% rename from packages/cross_file/lib/src/x_file.dart rename to packages/cross_file/cross_file/lib/src/x_file.dart diff --git a/packages/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml similarity index 100% rename from packages/cross_file/pubspec.yaml rename to packages/cross_file/cross_file/pubspec.yaml diff --git a/packages/cross_file/test/assets/hello.txt b/packages/cross_file/cross_file/test/assets/hello.txt similarity index 100% rename from packages/cross_file/test/assets/hello.txt rename to packages/cross_file/cross_file/test/assets/hello.txt diff --git a/packages/cross_file/test/x_file_html_test.dart b/packages/cross_file/cross_file/test/x_file_html_test.dart similarity index 100% rename from packages/cross_file/test/x_file_html_test.dart rename to packages/cross_file/cross_file/test/x_file_html_test.dart diff --git a/packages/cross_file/test/x_file_io_test.dart b/packages/cross_file/cross_file/test/x_file_io_test.dart similarity index 100% rename from packages/cross_file/test/x_file_io_test.dart rename to packages/cross_file/cross_file/test/x_file_io_test.dart From 6a0320b3594f481f166e3fc674b1bdc8e17c01db Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:40:56 -0500 Subject: [PATCH 002/398] initial flutter create for platform interface --- .../cross_file_platform_interface/.gitignore | 31 +++++++++++ .../cross_file_platform_interface/.metadata | 10 ++++ .../CHANGELOG.md | 3 ++ .../cross_file_platform_interface/LICENSE | 1 + .../cross_file_platform_interface/README.md | 39 ++++++++++++++ .../analysis_options.yaml | 4 ++ .../lib/cross_file_platform_interface.dart | 5 ++ .../pubspec.yaml | 54 +++++++++++++++++++ .../cross_file_platform_interface_test.dart | 12 +++++ 9 files changed, 159 insertions(+) create mode 100644 packages/cross_file/cross_file_platform_interface/.gitignore create mode 100644 packages/cross_file/cross_file_platform_interface/.metadata create mode 100644 packages/cross_file/cross_file_platform_interface/CHANGELOG.md create mode 100644 packages/cross_file/cross_file_platform_interface/LICENSE create mode 100644 packages/cross_file/cross_file_platform_interface/README.md create mode 100644 packages/cross_file/cross_file_platform_interface/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart create mode 100644 packages/cross_file/cross_file_platform_interface/pubspec.yaml create mode 100644 packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart diff --git a/packages/cross_file/cross_file_platform_interface/.gitignore b/packages/cross_file/cross_file_platform_interface/.gitignore new file mode 100644 index 000000000000..dd5eb98951f2 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/.gitignore @@ -0,0 +1,31 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/packages/cross_file/cross_file_platform_interface/.metadata b/packages/cross_file/cross_file_platform_interface/.metadata new file mode 100644 index 000000000000..9fc762cb6a19 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "81928eeb91fcdb2bc7a2dc35622627b31581549f" + channel: "main" + +project_type: package diff --git a/packages/cross_file/cross_file_platform_interface/CHANGELOG.md b/packages/cross_file/cross_file_platform_interface/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_platform_interface/LICENSE b/packages/cross_file/cross_file_platform_interface/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/cross_file/cross_file_platform_interface/README.md b/packages/cross_file/cross_file_platform_interface/README.md new file mode 100644 index 000000000000..4a260d8d279a --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/packages/cross_file/cross_file_platform_interface/analysis_options.yaml b/packages/cross_file/cross_file_platform_interface/analysis_options.yaml new file mode 100644 index 000000000000..a5744c1cfbe7 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart new file mode 100644 index 000000000000..298576d81397 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -0,0 +1,5 @@ +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/packages/cross_file/cross_file_platform_interface/pubspec.yaml b/packages/cross_file/cross_file_platform_interface/pubspec.yaml new file mode 100644 index 000000000000..4e2737300675 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/pubspec.yaml @@ -0,0 +1,54 @@ +name: cross_file_platform_interface +description: "A new Flutter package project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.10.0-200.0.dev + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart new file mode 100644 index 000000000000..f13a620eb830 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} From 4273a6383ed834edfac3edc66bc4f097ddbbba00 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:47:04 -0500 Subject: [PATCH 003/398] make same to other packages --- .../cross_file_platform_interface/.gitignore | 31 ------------ .../cross_file_platform_interface/.metadata | 10 ---- .../cross_file_platform_interface/LICENSE | 26 +++++++++- .../analysis_options.yaml | 4 -- .../pubspec.yaml | 50 ++++--------------- 5 files changed, 34 insertions(+), 87 deletions(-) delete mode 100644 packages/cross_file/cross_file_platform_interface/.gitignore delete mode 100644 packages/cross_file/cross_file_platform_interface/.metadata delete mode 100644 packages/cross_file/cross_file_platform_interface/analysis_options.yaml diff --git a/packages/cross_file/cross_file_platform_interface/.gitignore b/packages/cross_file/cross_file_platform_interface/.gitignore deleted file mode 100644 index dd5eb98951f2..000000000000 --- a/packages/cross_file/cross_file_platform_interface/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/cross_file/cross_file_platform_interface/.metadata b/packages/cross_file/cross_file_platform_interface/.metadata deleted file mode 100644 index 9fc762cb6a19..000000000000 --- a/packages/cross_file/cross_file_platform_interface/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "81928eeb91fcdb2bc7a2dc35622627b31581549f" - channel: "main" - -project_type: package diff --git a/packages/cross_file/cross_file_platform_interface/LICENSE b/packages/cross_file/cross_file_platform_interface/LICENSE index ba75c69f7f21..29b709dac6c7 100644 --- a/packages/cross_file/cross_file_platform_interface/LICENSE +++ b/packages/cross_file/cross_file_platform_interface/LICENSE @@ -1 +1,25 @@ -TODO: Add your license here. +Copyright 2013 The Flutter Authors + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/cross_file/cross_file_platform_interface/analysis_options.yaml b/packages/cross_file/cross_file_platform_interface/analysis_options.yaml deleted file mode 100644 index a5744c1cfbe7..000000000000 --- a/packages/cross_file/cross_file_platform_interface/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_platform_interface/pubspec.yaml b/packages/cross_file/cross_file_platform_interface/pubspec.yaml index 4e2737300675..035dae5c9cbd 100644 --- a/packages/cross_file/cross_file_platform_interface/pubspec.yaml +++ b/packages/cross_file/cross_file_platform_interface/pubspec.yaml @@ -1,11 +1,14 @@ name: cross_file_platform_interface -description: "A new Flutter package project." +description: A common platform interface for the cross_file plugin. +repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_platform_interface +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 +# 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: 0.0.1 -homepage: environment: - sdk: ^3.10.0-200.0.dev - flutter: ">=1.17.0" + sdk: ^3.7.0 + flutter: ">=3.29.0" dependencies: flutter: @@ -14,41 +17,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^6.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/to/font-from-package +topics: + - files From bfdb21c7dd57ba6e10ea7a364e07f1553a753fed Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 4 Nov 2025 10:46:21 -0500 Subject: [PATCH 004/398] start of interface updateF --- .../lib/cross_file_platform_interface.dart | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index 298576d81397..b1c2f803724e 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -1,5 +1,37 @@ -/// A Calculator. -class Calculator { - /// Returns [value] plus 1. - int addOne(int value) => value + 1; +// Platform Interface +import 'package:flutter/foundation.dart'; + +abstract base class CrossFilePlatform { + static CrossFilePlatform? instance; + + PlatformXFile createPlatformXFile( + PlatformBatteryManagerCreationParams params, + ); +} + +@immutable +base class PlatformBatteryManagerCreationParams { + const PlatformBatteryManagerCreationParams(); +} + +base class PlatformXFile { + factory PlatformXFile(PlatformBatteryManagerCreationParams params) { + assert(CrossFilePlatform.instance != null); + final PlatformXFile implementation = CrossFilePlatform.instance! + .createPlatformBatteryManager(params); + return implementation; + } + + @protected + PlatformBatteryManager.implementation(this.params); + + final PlatformBatteryManagerCreationParams params; + + PlatformBatteryManagerExtension? get extension => null; + + Future getLevel() { + throw UnimplementedError( + 'getLevel is not implemented on the current platform', + ); + } } From 7342a96e737def8c249374d56249b6bf1cccb84c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 10 Nov 2025 13:19:23 -0500 Subject: [PATCH 005/398] base xfile returns path --- .../lib/cross_file_platform_interface.dart | 38 ++----------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index b1c2f803724e..49bc10b38e76 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -1,37 +1,5 @@ // Platform Interface -import 'package:flutter/foundation.dart'; -abstract base class CrossFilePlatform { - static CrossFilePlatform? instance; - - PlatformXFile createPlatformXFile( - PlatformBatteryManagerCreationParams params, - ); -} - -@immutable -base class PlatformBatteryManagerCreationParams { - const PlatformBatteryManagerCreationParams(); -} - -base class PlatformXFile { - factory PlatformXFile(PlatformBatteryManagerCreationParams params) { - assert(CrossFilePlatform.instance != null); - final PlatformXFile implementation = CrossFilePlatform.instance! - .createPlatformBatteryManager(params); - return implementation; - } - - @protected - PlatformBatteryManager.implementation(this.params); - - final PlatformBatteryManagerCreationParams params; - - PlatformBatteryManagerExtension? get extension => null; - - Future getLevel() { - throw UnimplementedError( - 'getLevel is not implemented on the current platform', - ); - } -} +abstract base class XFile { + String get path; +} \ No newline at end of file From 1613f5291563e05d495eb081de68c341870e414c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:26:03 -0500 Subject: [PATCH 006/398] initial android impl --- .../cross_file/cross_file_android/.gitignore | 33 ++++++ .../cross_file/cross_file_android/.metadata | 30 +++++ .../cross_file_android/CHANGELOG.md | 3 + .../cross_file/cross_file_android/LICENSE | 1 + .../cross_file/cross_file_android/README.md | 15 +++ .../cross_file_android/analysis_options.yaml | 4 + .../cross_file_android/android/.gitignore | 9 ++ .../cross_file_android/android/build.gradle | 66 +++++++++++ .../android/settings.gradle | 1 + .../android/src/main/AndroidManifest.xml | 3 + .../CrossFileAndroidPlugin.kt | 38 +++++++ .../CrossFileAndroidPluginTest.kt | 27 +++++ .../cross_file_android/example/.gitignore | 45 ++++++++ .../cross_file_android/example/README.md | 16 +++ .../example/analysis_options.yaml | 28 +++++ .../example/android/.gitignore | 14 +++ .../example/android/app/build.gradle.kts | 44 +++++++ .../android/app/src/debug/AndroidManifest.xml | 7 ++ .../android/app/src/main/AndroidManifest.xml | 45 ++++++++ .../MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 ++ .../main/res/drawable/launch_background.xml | 12 ++ .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 +++ .../app/src/main/res/values/styles.xml | 18 +++ .../app/src/profile/AndroidManifest.xml | 7 ++ .../example/android/build.gradle.kts | 24 ++++ .../example/android/gradle.properties | 2 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../example/android/settings.gradle.kts | 26 +++++ .../plugin_integration_test.dart | 25 ++++ .../cross_file_android/example/lib/main.dart | 63 +++++++++++ .../cross_file_android/example/pubspec.yaml | 85 ++++++++++++++ .../example/test/widget_test.dart | 27 +++++ .../lib/cross_file_android.dart | 8 ++ .../cross_file_android_method_channel.dart | 17 +++ ...cross_file_android_platform_interface.dart | 29 +++++ .../cross_file_android/pubspec.yaml | 107 ++++++++++++++++++ ...ross_file_android_method_channel_test.dart | 27 +++++ .../test/cross_file_android_test.dart | 29 +++++ 44 files changed, 975 insertions(+) create mode 100644 packages/cross_file/cross_file_android/.gitignore create mode 100644 packages/cross_file/cross_file_android/.metadata create mode 100644 packages/cross_file/cross_file_android/CHANGELOG.md create mode 100644 packages/cross_file/cross_file_android/LICENSE create mode 100644 packages/cross_file/cross_file_android/README.md create mode 100644 packages/cross_file/cross_file_android/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_android/android/.gitignore create mode 100644 packages/cross_file/cross_file_android/android/build.gradle create mode 100644 packages/cross_file/cross_file_android/android/settings.gradle create mode 100644 packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt create mode 100644 packages/cross_file/cross_file_android/example/.gitignore create mode 100644 packages/cross_file/cross_file_android/example/README.md create mode 100644 packages/cross_file/cross_file_android/example/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_android/example/android/.gitignore create mode 100644 packages/cross_file/cross_file_android/example/android/app/build.gradle.kts create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/MainActivity.kt create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file_android/example/android/build.gradle.kts create mode 100644 packages/cross_file/cross_file_android/example/android/gradle.properties create mode 100644 packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/cross_file/cross_file_android/example/android/settings.gradle.kts create mode 100644 packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart create mode 100644 packages/cross_file/cross_file_android/example/lib/main.dart create mode 100644 packages/cross_file/cross_file_android/example/pubspec.yaml create mode 100644 packages/cross_file/cross_file_android/example/test/widget_test.dart create mode 100644 packages/cross_file/cross_file_android/lib/cross_file_android.dart create mode 100644 packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart create mode 100644 packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart create mode 100644 packages/cross_file/cross_file_android/pubspec.yaml create mode 100644 packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart create mode 100644 packages/cross_file/cross_file_android/test/cross_file_android_test.dart diff --git a/packages/cross_file/cross_file_android/.gitignore b/packages/cross_file/cross_file_android/.gitignore new file mode 100644 index 000000000000..b9d7f25b91b6 --- /dev/null +++ b/packages/cross_file/cross_file_android/.gitignore @@ -0,0 +1,33 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/packages/cross_file/cross_file_android/.metadata b/packages/cross_file/cross_file_android/.metadata new file mode 100644 index 000000000000..4c1a47f79ebd --- /dev/null +++ b/packages/cross_file/cross_file_android/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "81928eeb91fcdb2bc7a2dc35622627b31581549f" + channel: "main" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + - platform: android + create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_android/CHANGELOG.md b/packages/cross_file/cross_file_android/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/cross_file/cross_file_android/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_android/LICENSE b/packages/cross_file/cross_file_android/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/cross_file/cross_file_android/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/cross_file/cross_file_android/README.md b/packages/cross_file/cross_file_android/README.md new file mode 100644 index 000000000000..f6f307112a6e --- /dev/null +++ b/packages/cross_file/cross_file_android/README.md @@ -0,0 +1,15 @@ +# cross_file_android + +A new Flutter plugin project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/to/develop-plugins), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/packages/cross_file/cross_file_android/analysis_options.yaml b/packages/cross_file/cross_file_android/analysis_options.yaml new file mode 100644 index 000000000000..a5744c1cfbe7 --- /dev/null +++ b/packages/cross_file/cross_file_android/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_android/android/.gitignore b/packages/cross_file/cross_file_android/android/.gitignore new file mode 100644 index 000000000000..161bdcdaf88c --- /dev/null +++ b/packages/cross_file/cross_file_android/android/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +.cxx diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle new file mode 100644 index 000000000000..be1e09f4b771 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/build.gradle @@ -0,0 +1,66 @@ +group = "dev.flutter.packages.cross_file_android" +version = "1.0-SNAPSHOT" + +buildscript { + ext.kotlin_version = "2.1.0" + repositories { + google() + mavenCentral() + } + + dependencies { + classpath("com.android.tools.build:gradle:8.9.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +apply plugin: "com.android.library" +apply plugin: "kotlin-android" + +android { + namespace = "dev.flutter.packages.cross_file_android" + + compileSdk = 36 + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11 + } + + sourceSets { + main.java.srcDirs += "src/main/kotlin" + test.java.srcDirs += "src/test/kotlin" + } + + defaultConfig { + minSdk = 24 + } + + dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-test") + testImplementation("org.mockito:mockito-core:5.0.0") + } + + testOptions { + unitTests.all { + useJUnitPlatform() + + testLogging { + events "passed", "skipped", "failed", "standardOut", "standardError" + outputs.upToDateWhen {false} + showStandardStreams = true + } + } + } +} diff --git a/packages/cross_file/cross_file_android/android/settings.gradle b/packages/cross_file/cross_file_android/android/settings.gradle new file mode 100644 index 000000000000..3800a971764d --- /dev/null +++ b/packages/cross_file/cross_file_android/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'cross_file_android' diff --git a/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml b/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..5ac3f7b5b2af --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml @@ -0,0 +1,3 @@ + + diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt new file mode 100644 index 000000000000..66090e265674 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt @@ -0,0 +1,38 @@ +package dev.flutter.packages.cross_file_android + +import io.flutter.embedding.engine.plugins.FlutterPlugin +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import io.flutter.plugin.common.MethodChannel.Result + +/** CrossFileAndroidPlugin */ +class CrossFileAndroidPlugin : + FlutterPlugin, + MethodCallHandler { + // The MethodChannel that will the communication between Flutter and native Android + // + // This local reference serves to register the plugin with the Flutter Engine and unregister it + // when the Flutter Engine is detached from the Activity + private lateinit var channel: MethodChannel + + override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { + channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cross_file_android") + channel.setMethodCallHandler(this) + } + + override fun onMethodCall( + call: MethodCall, + result: Result + ) { + if (call.method == "getPlatformVersion") { + result.success("Android ${android.os.Build.VERSION.RELEASE}") + } else { + result.notImplemented() + } + } + + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + channel.setMethodCallHandler(null) + } +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt new file mode 100644 index 000000000000..913c6550dbcb --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt @@ -0,0 +1,27 @@ +package dev.flutter.packages.cross_file_android + +import io.flutter.plugin.common.MethodCall +import io.flutter.plugin.common.MethodChannel +import org.mockito.Mockito +import kotlin.test.Test + +/* + * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. + * + * Once you have built the plugin's example app, you can run these tests from the command + * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or + * you can run them directly from IDEs that support JUnit such as Android Studio. + */ + +internal class CrossFileAndroidPluginTest { + @Test + fun onMethodCall_getPlatformVersion_returnsExpectedValue() { + val plugin = CrossFileAndroidPlugin() + + val call = MethodCall("getPlatformVersion", null) + val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) + plugin.onMethodCall(call, mockResult) + + Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) + } +} diff --git a/packages/cross_file/cross_file_android/example/.gitignore b/packages/cross_file/cross_file_android/example/.gitignore new file mode 100644 index 000000000000..3820a95c65c3 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/cross_file/cross_file_android/example/README.md b/packages/cross_file/cross_file_android/example/README.md new file mode 100644 index 000000000000..18ce85271cd6 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/README.md @@ -0,0 +1,16 @@ +# cross_file_android_example + +Demonstrates how to use the cross_file_android plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/cross_file/cross_file_android/example/analysis_options.yaml b/packages/cross_file/cross_file_android/example/analysis_options.yaml new file mode 100644 index 000000000000..0d2902135cae --- /dev/null +++ b/packages/cross_file/cross_file_android/example/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_android/example/android/.gitignore b/packages/cross_file/cross_file_android/example/android/.gitignore new file mode 100644 index 000000000000..be3943c96d8e --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts new file mode 100644 index 000000000000..28a028671da1 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "dev.flutter.packages.cross_file_android_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "dev.flutter.packages.cross_file_android_example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml b/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000000..399f6981d5d3 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/AndroidManifest.xml b/packages/cross_file/cross_file_android/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..3d3a2a209ab2 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/MainActivity.kt b/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/MainActivity.kt new file mode 100644 index 000000000000..c2563cc4d5f5 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/MainActivity.kt @@ -0,0 +1,5 @@ +package dev.flutter.packages.cross_file_android_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000000..f74085f3f6a2 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable/launch_background.xml b/packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000000..304732f88420 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/cross_file/cross_file_android/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/values-night/styles.xml b/packages/cross_file/cross_file_android/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000000..06952be745f9 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/res/values/styles.xml b/packages/cross_file/cross_file_android/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000000..cb1ef88056ed --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/profile/AndroidManifest.xml b/packages/cross_file/cross_file_android/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000000..399f6981d5d3 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/cross_file/cross_file_android/example/android/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/build.gradle.kts new file mode 100644 index 000000000000..dbee657bb5b9 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/packages/cross_file/cross_file_android/example/android/gradle.properties b/packages/cross_file/cross_file_android/example/android/gradle.properties new file mode 100644 index 000000000000..fbee1d8cdafc --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..ac3b47926ee5 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip diff --git a/packages/cross_file/cross_file_android/example/android/settings.gradle.kts b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts new file mode 100644 index 000000000000..fb605bc840f7 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.9.1" apply false + id("org.jetbrains.kotlin.android") version "2.1.0" apply false +} + +include(":app") diff --git a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart new file mode 100644 index 000000000000..e0bc36a40144 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart @@ -0,0 +1,25 @@ +// This is a basic Flutter integration test. +// +// Since integration tests run in a full Flutter application, they can interact +// with the host side of a plugin implementation, unlike Dart unit tests. +// +// For more information about Flutter integration tests, please see +// https://flutter.dev/to/integration-testing + + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:cross_file_android/cross_file_android.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getPlatformVersion test', (WidgetTester tester) async { + final CrossFileAndroid plugin = CrossFileAndroid(); + final String? version = await plugin.getPlatformVersion(); + // The version string depends on the host platform running the test, so + // just assert that some non-empty string is returned. + expect(version?.isNotEmpty, true); + }); +} diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart new file mode 100644 index 000000000000..1f1c2863db04 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:cross_file_android/cross_file_android.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + String _platformVersion = 'Unknown'; + final _crossFileAndroidPlugin = CrossFileAndroid(); + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initPlatformState() async { + String platformVersion; + // Platform messages may fail, so we use a try/catch PlatformException. + // We also handle the message potentially returning null. + try { + platformVersion = + await _crossFileAndroidPlugin.getPlatformVersion() ?? 'Unknown platform version'; + } on PlatformException { + platformVersion = 'Failed to get platform version.'; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) return; + + setState(() { + _platformVersion = platformVersion; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + child: Text('Running on: $_platformVersion\n'), + ), + ), + ); + } +} diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml new file mode 100644 index 000000000000..fd16bbfd3e0f --- /dev/null +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -0,0 +1,85 @@ +name: cross_file_android_example +description: "Demonstrates how to use the cross_file_android plugin." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ^3.10.0-200.0.dev + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + cross_file_android: + # When depending on this package from a real application you should use: + # cross_file_android: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_android/example/test/widget_test.dart b/packages/cross_file/cross_file_android/example/test/widget_test.dart new file mode 100644 index 000000000000..930511fbd8d4 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cross_file_android_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => widget is Text && + widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart new file mode 100644 index 000000000000..eae62d6c66bc --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -0,0 +1,8 @@ + +import 'cross_file_android_platform_interface.dart'; + +class CrossFileAndroid { + Future getPlatformVersion() { + return CrossFileAndroidPlatform.instance.getPlatformVersion(); + } +} diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart b/packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart new file mode 100644 index 000000000000..06465df10ebd --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart @@ -0,0 +1,17 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'cross_file_android_platform_interface.dart'; + +/// An implementation of [CrossFileAndroidPlatform] that uses method channels. +class MethodChannelCrossFileAndroid extends CrossFileAndroidPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + final methodChannel = const MethodChannel('cross_file_android'); + + @override + Future getPlatformVersion() async { + final version = await methodChannel.invokeMethod('getPlatformVersion'); + return version; + } +} diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart b/packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart new file mode 100644 index 000000000000..e8b6b5d4fb4f --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart @@ -0,0 +1,29 @@ +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'cross_file_android_method_channel.dart'; + +abstract class CrossFileAndroidPlatform extends PlatformInterface { + /// Constructs a CrossFileAndroidPlatform. + CrossFileAndroidPlatform() : super(token: _token); + + static final Object _token = Object(); + + static CrossFileAndroidPlatform _instance = MethodChannelCrossFileAndroid(); + + /// The default instance of [CrossFileAndroidPlatform] to use. + /// + /// Defaults to [MethodChannelCrossFileAndroid]. + static CrossFileAndroidPlatform get instance => _instance; + + /// Platform-specific implementations should set this with their own + /// platform-specific class that extends [CrossFileAndroidPlatform] when + /// they register themselves. + static set instance(CrossFileAndroidPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Future getPlatformVersion() { + throw UnimplementedError('platformVersion() has not been implemented.'); + } +} diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml new file mode 100644 index 000000000000..654b4d9e4a42 --- /dev/null +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -0,0 +1,107 @@ +name: cross_file_android +description: Some something darkside +repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 +version: 4.10.5 + +environment: + sdk: ^3.9.0 + flutter: ">=3.35.0" + +flutter: + plugin: + implements: webview_flutter + platforms: + android: + package: io.flutter.plugins.webviewflutter + pluginClass: WebViewFlutterPlugin + dartPluginClass: AndroidWebViewPlatform + +dependencies: + flutter: + sdk: flutter + meta: ^1.10.0 + webview_flutter_platform_interface: ^2.14.0 + +dev_dependencies: + build_runner: ^2.1.4 + flutter_test: + sdk: flutter + mockito: ^5.4.4 + pigeon: ^25.3.2 + +topics: + - html + - webview + - webview-flutter + +name: cross_file_android +description: "A new Flutter plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.10.0-200.0.dev + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) + # which should be registered in the plugin registry. This is required for + # using method channels. + # The Android 'package' specifies package in which the registered class is. + # This is required for using method channels on Android. + # The 'ffiPlugin' specifies that native code should be built and bundled. + # This is required for using `dart:ffi`. + # All these are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + android: + package: dev.flutter.packages.cross_file_android + pluginClass: CrossFileAndroidPlugin + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart b/packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart new file mode 100644 index 000000000000..75db4051ba41 --- /dev/null +++ b/packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart @@ -0,0 +1,27 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_android/cross_file_android_method_channel.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + MethodChannelCrossFileAndroid platform = MethodChannelCrossFileAndroid(); + const MethodChannel channel = MethodChannel('cross_file_android'); + + setUp(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + channel, + (MethodCall methodCall) async { + return '42'; + }, + ); + }); + + tearDown(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null); + }); + + test('getPlatformVersion', () async { + expect(await platform.getPlatformVersion(), '42'); + }); +} diff --git a/packages/cross_file/cross_file_android/test/cross_file_android_test.dart b/packages/cross_file/cross_file_android/test/cross_file_android_test.dart new file mode 100644 index 000000000000..e7764d7e4407 --- /dev/null +++ b/packages/cross_file/cross_file_android/test/cross_file_android_test.dart @@ -0,0 +1,29 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_android/cross_file_android.dart'; +import 'package:cross_file_android/cross_file_android_platform_interface.dart'; +import 'package:cross_file_android/cross_file_android_method_channel.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockCrossFileAndroidPlatform + with MockPlatformInterfaceMixin + implements CrossFileAndroidPlatform { + + @override + Future getPlatformVersion() => Future.value('42'); +} + +void main() { + final CrossFileAndroidPlatform initialPlatform = CrossFileAndroidPlatform.instance; + + test('$MethodChannelCrossFileAndroid is the default instance', () { + expect(initialPlatform, isInstanceOf()); + }); + + test('getPlatformVersion', () async { + CrossFileAndroid crossFileAndroidPlugin = CrossFileAndroid(); + MockCrossFileAndroidPlatform fakePlatform = MockCrossFileAndroidPlatform(); + CrossFileAndroidPlatform.instance = fakePlatform; + + expect(await crossFileAndroidPlugin.getPlatformVersion(), '42'); + }); +} From 326f932579ce78efcdc890ef815ad8b1bd02e808 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 10 Nov 2025 19:20:03 -0500 Subject: [PATCH 007/398] create platform interface --- .../cross_file_android/pubspec.yaml | 95 +++---------------- .../lib/cross_file_platform_interface.dart | 30 +++++- 2 files changed, 38 insertions(+), 87 deletions(-) diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 654b4d9e4a42..123a1406c3ca 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -2,7 +2,8 @@ name: cross_file_android description: Some something darkside repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 4.10.5 +version: 0.0.1 +publish_to: none environment: sdk: ^3.9.0 @@ -10,98 +11,24 @@ environment: flutter: plugin: - implements: webview_flutter + implements: cross_file platforms: android: - package: io.flutter.plugins.webviewflutter - pluginClass: WebViewFlutterPlugin - dartPluginClass: AndroidWebViewPlatform + package: dev.flutter.packages.cross_file_android + pluginClass: CrossFileAndroidPlugin + dartPluginClass: CrossFileAndroid dependencies: + file: ^7.0.1 flutter: sdk: flutter - meta: ^1.10.0 - webview_flutter_platform_interface: ^2.14.0 + cross_file_platform_interface: + path: ../cross_file_platform_interface dev_dependencies: - build_runner: ^2.1.4 flutter_test: sdk: flutter - mockito: ^5.4.4 - pigeon: ^25.3.2 + pigeon: ^26.0.5 topics: - - html - - webview - - webview-flutter - -name: cross_file_android -description: "A new Flutter plugin project." -version: 0.0.1 -homepage: - -environment: - sdk: ^3.10.0-200.0.dev - flutter: '>=3.3.0' - -dependencies: - flutter: - sdk: flutter - plugin_platform_interface: ^2.0.2 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - # This section identifies this Flutter project as a plugin project. - # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) - # which should be registered in the plugin registry. This is required for - # using method channels. - # The Android 'package' specifies package in which the registered class is. - # This is required for using method channels on Android. - # The 'ffiPlugin' specifies that native code should be built and bundled. - # This is required for using `dart:ffi`. - # All these are used by the tooling to maintain consistency when - # adding or updating assets for this project. - plugin: - platforms: - android: - package: dev.flutter.packages.cross_file_android - pluginClass: CrossFileAndroidPlugin - - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # To add custom fonts to your plugin package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/to/font-from-package + - file diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index 49bc10b38e76..c734550d2c2f 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -1,5 +1,29 @@ // Platform Interface -abstract base class XFile { - String get path; -} \ No newline at end of file +import 'dart:convert'; +import 'dart:typed_data'; + +abstract base class XFilePlatform { + static XFilePlatform? instance; + + PlatformXFile createPlatformXFile(String path); +} + +abstract base class PlatformXFile { + PlatformXFile(this.path); + + final String path; + + Future lastModified(); + + /// Reads the entire file contents as a list of bytes. + Future readAsBytes(); + + /// Reads the entire file contents as a string using the given Encoding. + Future readAsString({Encoding encoding = utf8}); + + /// The length of the file. + Future length(); + + Stream openRead([int? start, int? end]); +} From 2f2f17c4a2d0e5b670aeba2528ec35ee082195b5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Nov 2025 10:41:18 -0500 Subject: [PATCH 008/398] some android push --- .../cross_file_android/android/build.gradle | 1 + .../cross_file_android/DocumentFile.g.kt | 534 +++++++++++++++++ .../lib/cross_file_android.dart | 45 +- .../cross_file_android_method_channel.dart | 17 - ...cross_file_android_platform_interface.dart | 29 - .../lib/src/android_cross_file.dart | 41 ++ .../lib/src/android_cross_file_extension.dart | 5 + .../lib/src/android_file.dart | 292 +++++++++ .../lib/src/android_file_system.dart | 71 +++ .../lib/src/android_file_system_entity.dart | 41 ++ .../lib/src/cross_file_android.dart | 14 + .../lib/src/document_file.g.dart | 563 ++++++++++++++++++ .../cross_file_android/pigeons/copyright.txt | 3 + .../pigeons/document_file.dart | 21 + .../cross_file_android/pubspec.yaml | 2 +- ...ross_file_android_method_channel_test.dart | 27 - .../test/cross_file_android_test.dart | 29 - .../lib/cross_file_platform_interface.dart | 6 +- 18 files changed, 1633 insertions(+), 108 deletions(-) create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt delete mode 100644 packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart delete mode 100644 packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/android_cross_file.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/android_file.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/android_file_system.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/cross_file_android.dart create mode 100644 packages/cross_file/cross_file_android/lib/src/document_file.g.dart create mode 100644 packages/cross_file/cross_file_android/pigeons/copyright.txt create mode 100644 packages/cross_file/cross_file_android/pigeons/document_file.dart delete mode 100644 packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart delete mode 100644 packages/cross_file/cross_file_android/test/cross_file_android_test.dart diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle index be1e09f4b771..70684cf06378 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle +++ b/packages/cross_file/cross_file_android/android/build.gradle @@ -48,6 +48,7 @@ android { } dependencies { + implementation "androidx.documentfile:documentfile:1.1.0" testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.mockito:mockito-core:5.0.0") } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt new file mode 100644 index 000000000000..99c347839ad1 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt @@ -0,0 +1,534 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.0.5), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package dev.flutter.packages.cross_file_android + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer +private object DocumentFilePigeonUtils { + + fun createConnectionError(channelName: String): FlutterError { + return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + + fun wrapResult(result: Any?): List { + return listOf(result) + } + + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +/** + * Maintains instances used to communicate with the corresponding objects in Dart. + * + * Objects stored in this container are represented by an object in Dart that is also stored in + * an InstanceManager with the same identifier. + * + * When an instance is added with an identifier, either can be used to retrieve the other. + * + * Added instances are added as a weak reference and a strong reference. When the strong + * reference is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong + * reference is removed and then the identifier is retrieved with the intention to pass the identifier + * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance + * is recreated. The strong reference will then need to be removed manually again. + */ +@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") +class DocumentFilePigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ + interface PigeonFinalizationListener { + fun onFinalize(identifier: Long) + } + + // Extends WeakReference and overrides the `equals` and `hashCode` methods using identity rather + // than equality. + // + // Two `IdentityWeakReference`s are equal if either + // 1: `get()` returns the identical nonnull value for both references. + // 2: `get()` returns null for both references and the references are identical. + class IdentityWeakReference : java.lang.ref.WeakReference { + private val savedHashCode: Int + + constructor(instance: T) : this(instance, null) + + constructor(instance: T, queue: java.lang.ref.ReferenceQueue?) : super(instance, queue) { + savedHashCode = System.identityHashCode(instance) + } + + override fun equals(other: Any?): Boolean { + val instance = get() + if (instance != null) { + return other is IdentityWeakReference<*> && other.get() === instance + } + return other === this + } + + override fun hashCode(): Int { + return savedHashCode + } + } + + private val identifiers = java.util.WeakHashMap, Long>() + private val weakInstances = HashMap>() + private val strongInstances = HashMap() + private val referenceQueue = java.lang.ref.ReferenceQueue() + private val weakReferencesToIdentifiers = HashMap, Long>() + private val handler = android.os.Handler(android.os.Looper.getMainLooper()) + private val releaseAllFinalizedInstancesRunnable = Runnable { + this.releaseAllFinalizedInstances() + } + private var nextIdentifier: Long = minHostCreatedIdentifier + private var hasFinalizationListenerStopped = false + + /** + * Modifies the time interval used to define how often this instance removes garbage collected + * weak references to native Android objects that this instance was managing. + */ + var clearFinalizedWeakReferencesInterval: Long = 3000 + set(value) { + handler.removeCallbacks(releaseAllFinalizedInstancesRunnable) + field = value + releaseAllFinalizedInstances() + } + + init { + handler.postDelayed(releaseAllFinalizedInstancesRunnable, clearFinalizedWeakReferencesInterval) + } + + companion object { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private const val minHostCreatedIdentifier: Long = 65536 + private const val tag = "PigeonInstanceManager" + + /** + * Instantiate a new manager with a listener for garbage collected weak + * references. + * + * When the manager is no longer needed, [stopFinalizationListener] must be called. + */ + fun create(finalizationListener: PigeonFinalizationListener): DocumentFilePigeonInstanceManager { + return DocumentFilePigeonInstanceManager(finalizationListener) + } + } + + /** + * Removes `identifier` and return its associated strongly referenced instance, if present, + * from the manager. + */ + fun remove(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + return strongInstances.remove(identifier) as T? + } + + /** + * Retrieves the identifier paired with an instance, if present, otherwise `null`. + * + * + * If the manager contains a strong reference to `instance`, it will return the identifier + * associated with `instance`. If the manager contains only a weak reference to `instance`, a new + * strong reference to `instance` will be added and will need to be removed again with [remove]. + * + * + * If this method returns a nonnull identifier, this method also expects the Dart + * `DocumentFilePigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. + */ + fun getIdentifierForStrongReference(instance: Any?): Long? { + logWarningIfFinalizationListenerHasStopped() + if (instance == null) { + return null + } + val identifier = identifiers[IdentityWeakReference(instance)] + if (identifier != null) { + strongInstances[identifier] = instance + } + return identifier + } + + /** + * Adds a new instance that was instantiated from Dart. + * + * The same instance can be added multiple times, but each identifier must be unique. This + * allows two objects that are equivalent (e.g. the `equals` method returns true and their + * hashcodes are equal) to both be added. + * + * [identifier] must be >= 0 and unique. + */ + fun addDartCreatedInstance(instance: Any, identifier: Long) { + logWarningIfFinalizationListenerHasStopped() + addInstance(instance, identifier) + } + + /** + * Adds a new unique instance that was instantiated from the host platform. + * + * If the manager contains [instance], this returns the corresponding identifier. If the + * manager does not contain [instance], this adds the instance and returns a unique + * identifier for that [instance]. + */ + fun addHostCreatedInstance(instance: Any): Long { + logWarningIfFinalizationListenerHasStopped() + require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } + val identifier = nextIdentifier++ + addInstance(instance, identifier) + return identifier + } + + /** Retrieves the instance associated with identifier, if present, otherwise `null`. */ + fun getInstance(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + val instance = weakInstances[identifier] as IdentityWeakReference? + return instance?.get() + } + + /** Returns whether this manager contains the given `instance`. */ + fun containsInstance(instance: Any?): Boolean { + logWarningIfFinalizationListenerHasStopped() + return instance != null && identifiers.containsKey(IdentityWeakReference(instance)) + } + + /** + * Stops the periodic run of the [PigeonFinalizationListener] for instances that have been garbage + * collected. + * + * The InstanceManager can continue to be used, but the [PigeonFinalizationListener] will no + * longer be called and methods will log a warning. + */ + fun stopFinalizationListener() { + handler.removeCallbacks(releaseAllFinalizedInstancesRunnable) + hasFinalizationListenerStopped = true + } + + /** + * Removes all of the instances from this manager. + * + * The manager will be empty after this call returns. + */ + fun clear() { + identifiers.clear() + weakInstances.clear() + strongInstances.clear() + weakReferencesToIdentifiers.clear() + } + + /** + * Whether the [PigeonFinalizationListener] is still being called for instances that are garbage + * collected. + * + * See [stopFinalizationListener]. + */ + fun hasFinalizationListenerStopped(): Boolean { + return hasFinalizationListenerStopped + } + + private fun releaseAllFinalizedInstances() { + if (hasFinalizationListenerStopped()) { + return + } + var reference: IdentityWeakReference? + while ((referenceQueue.poll() as IdentityWeakReference?).also { reference = it } != null) { + val identifier = weakReferencesToIdentifiers.remove(reference) + if (identifier != null) { + weakInstances.remove(identifier) + strongInstances.remove(identifier) + finalizationListener.onFinalize(identifier) + } + } + handler.postDelayed(releaseAllFinalizedInstancesRunnable, clearFinalizedWeakReferencesInterval) + } + + private fun addInstance(instance: Any, identifier: Long) { + require(identifier >= 0) { "Identifier must be >= 0: $identifier" } + require(!weakInstances.containsKey(identifier)) { + "Identifier has already been added: $identifier" + } + val weakReference = IdentityWeakReference(instance, referenceQueue) + identifiers[weakReference] = identifier + weakInstances[identifier] = weakReference + weakReferencesToIdentifiers[weakReference] = identifier + strongInstances[identifier] = instance + } + + private fun logWarningIfFinalizationListenerHasStopped() { + if (hasFinalizationListenerStopped()) { + Log.w( + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped." + ) + } + } +} + + +/** Generated API for managing the Dart and native `InstanceManager`s. */ +private class DocumentFilePigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { + companion object { + /** The codec used by DocumentFilePigeonInstanceManagerApi. */ + val codec: MessageCodec by lazy { + DocumentFilePigeonCodec() + } + + /** + * Sets up an instance of `DocumentFilePigeonInstanceManagerApi` to handle messages from the + * `binaryMessenger`. + */ + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: DocumentFilePigeonInstanceManager?) { + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) + if (instanceManager != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val identifierArg = args[0] as Long + val wrapped: List = try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) + if (instanceManager != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) +{ + val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) + } + } + } +} +/** + * Provides implementations for each ProxyApi implementation and provides access to resources + * needed by any implementation. + */ +abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { + /** Whether APIs should ignore calling to Dart. */ + public var ignoreCallsToDart = false + val instanceManager: DocumentFilePigeonInstanceManager + private var _codec: MessageCodec? = null + val codec: MessageCodec + get() { + if (_codec == null) { + _codec = DocumentFilePigeonProxyApiBaseCodec(this) + } + return _codec!! + } + + init { + val api = DocumentFilePigeonInstanceManagerApi(binaryMessenger) + instanceManager = DocumentFilePigeonInstanceManager.create( + object : DocumentFilePigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier" + ) + } + } + } + } + ) + } + /** + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of + * `DocumentFile` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile + + fun setUp() { + DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, instanceManager) + PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, getPigeonApiDocumentFile()) + } + fun tearDown() { + DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) + PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) + } +} +private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePigeonProxyApiRegistrar) : DocumentFilePigeonCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + val identifier: Long = readValue(buffer) as Long + val instance: Any? = registrar.instanceManager.getInstance(identifier) + if (instance == null) { + Log.e( + "PigeonProxyApiBaseCodec", + "Failed to find instance with identifier: $identifier" + ) + } + return instance + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { + super.writeValue(stream, value) + return + } + + fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { + Log.w( + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception" + ) + } + + if (value is androidx.documentfile.provider.DocumentFile) { + registrar.getPigeonApiDocumentFile().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) + } + } + } + + when { + registrar.instanceManager.containsInstance(value) -> { + stream.write(128) + writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) + } + else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") + } + } +} +private open class DocumentFilePigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { + abstract fun fromSingleUri(path: String): androidx.documentfile.provider.DocumentFile + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { + val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0] as Long + val pathArg = args[1] as String + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(pathArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index eae62d6c66bc..3912d8b994b9 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -1,8 +1,45 @@ +import 'dart:convert'; -import 'cross_file_android_platform_interface.dart'; +import 'dart:typed_data'; -class CrossFileAndroid { - Future getPlatformVersion() { - return CrossFileAndroidPlatform.instance.getPlatformVersion(); +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:file/file.dart'; + +base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { + AndroidXFile(super.path); + + @override + PlatformXFileExtension? get extension { + return this; + } + + @override + Future lastModified() { + // TODO: implement lastModified + throw UnimplementedError(); + } + + @override + Future length() { + // TODO: implement length + throw UnimplementedError(); + } + + @override + Stream openRead([int? start, int? end]) { + // TODO: implement openRead + throw UnimplementedError(); + } + + @override + Future readAsBytes() { + // TODO: implement readAsBytes + throw UnimplementedError(); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + // TODO: implement readAsString + throw UnimplementedError(); } } diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart b/packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart deleted file mode 100644 index 06465df10ebd..000000000000 --- a/packages/cross_file/cross_file_android/lib/cross_file_android_method_channel.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -import 'cross_file_android_platform_interface.dart'; - -/// An implementation of [CrossFileAndroidPlatform] that uses method channels. -class MethodChannelCrossFileAndroid extends CrossFileAndroidPlatform { - /// The method channel used to interact with the native platform. - @visibleForTesting - final methodChannel = const MethodChannel('cross_file_android'); - - @override - Future getPlatformVersion() async { - final version = await methodChannel.invokeMethod('getPlatformVersion'); - return version; - } -} diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart b/packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart deleted file mode 100644 index e8b6b5d4fb4f..000000000000 --- a/packages/cross_file/cross_file_android/lib/cross_file_android_platform_interface.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -import 'cross_file_android_method_channel.dart'; - -abstract class CrossFileAndroidPlatform extends PlatformInterface { - /// Constructs a CrossFileAndroidPlatform. - CrossFileAndroidPlatform() : super(token: _token); - - static final Object _token = Object(); - - static CrossFileAndroidPlatform _instance = MethodChannelCrossFileAndroid(); - - /// The default instance of [CrossFileAndroidPlatform] to use. - /// - /// Defaults to [MethodChannelCrossFileAndroid]. - static CrossFileAndroidPlatform get instance => _instance; - - /// Platform-specific implementations should set this with their own - /// platform-specific class that extends [CrossFileAndroidPlatform] when - /// they register themselves. - static set instance(CrossFileAndroidPlatform instance) { - PlatformInterface.verifyToken(instance, _token); - _instance = instance; - } - - Future getPlatformVersion() { - throw UnimplementedError('platformVersion() has not been implemented.'); - } -} diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart new file mode 100644 index 000000000000..0ba43fb31d8f --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -0,0 +1,41 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { + AndroidXFile(super.path); + + @override + PlatformXFileExtension? get extension { + return this; + } + + @override + Future lastModified() { + // TODO: implement lastModified + throw UnimplementedError(); + } + + @override + Future length() { + // TODO: implement length + throw UnimplementedError(); + } + + @override + Stream openRead([int? start, int? end]) { + // TODO: implement openRead + throw UnimplementedError(); + } + + @override + Future readAsBytes() { + // TODO: implement readAsBytes + throw UnimplementedError(); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + // TODO: implement readAsString + throw UnimplementedError(); + } +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart new file mode 100644 index 000000000000..c3a13880fcf1 --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart @@ -0,0 +1,5 @@ +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +mixin AndroidXFileExtension implements PlatformXFileExtension { + +} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file.dart b/packages/cross_file/cross_file_android/lib/src/android_file.dart new file mode 100644 index 000000000000..5e3a20c8d48d --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/android_file.dart @@ -0,0 +1,292 @@ +import 'dart:convert'; + +import 'dart:typed_data'; + +import 'dart:io' as io; + +import 'package:cross_file_android/src/android_file_system.dart'; +import 'package:cross_file_android/src/android_file_system_entity.dart'; +import 'package:cross_file_android/src/document_file.g.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:file/file.dart'; + +base class AndroidFile extends PlatformXFile + with AndroidFileSystemEntity + implements File { + AndroidFile(super.path) + : _documentFile = DocumentFile.fromSingleUri(path: path); + + DocumentFile _documentFile; + + @override + File get absolute => fileSystem.file(path); + + @override + Future copy(String newPath) { + // TODO: implement copy + throw UnimplementedError(); + } + + @override + File copySync(String newPath) { + // TODO: implement copySync + throw UnimplementedError(); + } + + @override + Future create({bool recursive = false, bool exclusive = false}) { + // TODO: implement create + throw UnimplementedError(); + } + + @override + void createSync({bool recursive = false, bool exclusive = false}) { + // TODO: implement createSync + } + + @override + Future delete({bool recursive = false}) { + // TODO: implement delete + throw UnimplementedError(); + } + + @override + void deleteSync({bool recursive = false}) { + // TODO: implement deleteSync + } + + @override + // TODO: implement dirname + String get dirname => throw UnimplementedError(); + + @override + Future exists() { + // TODO: implement exists + throw UnimplementedError(); + } + + @override + bool existsSync() { + // TODO: implement existsSync + throw UnimplementedError(); + } + + @override + // TODO: implement isAbsolute + bool get isAbsolute => throw UnimplementedError(); + + @override + Future lastAccessed() { + // TODO: implement lastAccessed + throw UnimplementedError(); + } + + @override + DateTime lastAccessedSync() { + // TODO: implement lastAccessedSync + throw UnimplementedError(); + } + + @override + Future lastModified() { + // TODO: implement lastModified + throw UnimplementedError(); + } + + @override + DateTime lastModifiedSync() { + // TODO: implement lastModifiedSync + throw UnimplementedError(); + } + + @override + Future length() { + // TODO: implement length + throw UnimplementedError(); + } + + @override + int lengthSync() { + // TODO: implement lengthSync + throw UnimplementedError(); + } + + @override + Future open({FileMode mode = FileMode.read}) { + // TODO: implement open + throw UnimplementedError(); + } + + @override + Stream> openRead([int? start, int? end]) { + // TODO: implement openRead + throw UnimplementedError(); + } + + @override + RandomAccessFile openSync({FileMode mode = FileMode.read}) { + // TODO: implement openSync + throw UnimplementedError(); + } + + @override + IOSink openWrite({FileMode mode = FileMode.write, Encoding encoding = utf8}) { + // TODO: implement openWrite + throw UnimplementedError(); + } + + @override + // TODO: implement parent + Directory get parent => throw UnimplementedError(); + + @override + // TODO: implement path + String get path => throw UnimplementedError(); + + @override + Future readAsBytes() { + // TODO: implement readAsBytes + throw UnimplementedError(); + } + + @override + Uint8List readAsBytesSync() { + // TODO: implement readAsBytesSync + throw UnimplementedError(); + } + + @override + Future> readAsLines({Encoding encoding = utf8}) { + // TODO: implement readAsLines + throw UnimplementedError(); + } + + @override + List readAsLinesSync({Encoding encoding = utf8}) { + // TODO: implement readAsLinesSync + throw UnimplementedError(); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + // TODO: implement readAsString + throw UnimplementedError(); + } + + @override + String readAsStringSync({Encoding encoding = utf8}) { + // TODO: implement readAsStringSync + throw UnimplementedError(); + } + + @override + Future rename(String newPath) { + // TODO: implement rename + throw UnimplementedError(); + } + + @override + File renameSync(String newPath) { + // TODO: implement renameSync + throw UnimplementedError(); + } + + @override + Future resolveSymbolicLinks() { + // TODO: implement resolveSymbolicLinks + throw UnimplementedError(); + } + + @override + String resolveSymbolicLinksSync() { + // TODO: implement resolveSymbolicLinksSync + throw UnimplementedError(); + } + + @override + Future setLastAccessed(DateTime time) { + // TODO: implement setLastAccessed + throw UnimplementedError(); + } + + @override + void setLastAccessedSync(DateTime time) { + // TODO: implement setLastAccessedSync + } + + @override + Future setLastModified(DateTime time) { + // TODO: implement setLastModified + throw UnimplementedError(); + } + + @override + void setLastModifiedSync(DateTime time) { + // TODO: implement setLastModifiedSync + } + + @override + Future stat() { + // TODO: implement stat + throw UnimplementedError(); + } + + @override + FileStat statSync() { + // TODO: implement statSync + throw UnimplementedError(); + } + + @override + // TODO: implement uri + Uri get uri => throw UnimplementedError(); + + @override + Stream watch({ + int events = FileSystemEvent.all, + bool recursive = false, + }) { + // TODO: implement watch + throw UnimplementedError(); + } + + @override + Future writeAsBytes( + List bytes, { + FileMode mode = io.FileMode.write, + bool flush = false, + }) { + // TODO: implement writeAsBytes + throw UnimplementedError(); + } + + @override + void writeAsBytesSync( + List bytes, { + FileMode mode = FileMode.write, + bool flush = false, + }) { + // TODO: implement writeAsBytesSync + } + + @override + Future writeAsString( + String contents, { + FileMode mode = io.FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) { + // TODO: implement writeAsString + throw UnimplementedError(); + } + + @override + void writeAsStringSync( + String contents, { + FileMode mode = FileMode.write, + Encoding encoding = utf8, + bool flush = false, + }) { + // TODO: implement writeAsStringSync + } +} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file_system.dart b/packages/cross_file/cross_file_android/lib/src/android_file_system.dart new file mode 100644 index 000000000000..a7fbbc005fe5 --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/android_file_system.dart @@ -0,0 +1,71 @@ +import 'package:cross_file_android/src/document_file.g.dart'; +import 'package:file/file.dart'; +import 'package:path/src/context.dart'; + +class AndroidFileSystem extends FileSystem { + const AndroidFileSystem(); + + @override + Directory currentDirectory; + + @override + Directory directory(path) { + throw UnimplementedError(); + } + + @override + File file(path) { + throw UnimplementedError(); + } + + @override + Future identical(String path1, String path2) { + // TODO: implement identical + throw UnimplementedError(); + } + + @override + bool identicalSync(String path1, String path2) { + // TODO: implement identicalSync + throw UnimplementedError(); + } + + @override + // TODO: implement isWatchSupported + bool get isWatchSupported => throw UnimplementedError(); + + @override + Link link(path) { + // TODO: implement link + throw UnimplementedError(); + } + + @override + // TODO: implement path + Context get path => throw UnimplementedError(); + + @override + Future stat(String path) { + // TODO: implement stat + throw UnimplementedError(); + } + + @override + FileStat statSync(String path) { + throw UnimplementedError(); + } + + @override + Directory get systemTempDirectory => throw UnimplementedError(); + + @override + Future type(String path, {bool followLinks = true}) { + throw UnimplementedError(); + } + + @override + FileSystemEntityType typeSync(String path, {bool followLinks = true}) { + throw UnimplementedError(); + } + +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart b/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart new file mode 100644 index 000000000000..e3080cbf6dad --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart @@ -0,0 +1,41 @@ +import 'dart:io' as io; + +import 'package:cross_file_android/src/document_file.g.dart'; +import 'package:file/file.dart'; + +import 'android_file_system.dart'; + +mixin AndroidFileSystemEntity implements FileSystemEntity { + DocumentFile get nativeFile; + + /// Returns the file system responsible for this entity. + FileSystem get fileSystem => const AndroidFileSystem(); + + /// Gets the part of this entity's path after the last separator. + /// + /// context.basename('path/to/foo.dart'); // -> 'foo.dart' + /// context.basename('path/to'); // -> 'to' + /// + /// Trailing separators are ignored. + /// + /// context.basename('path/to/'); // -> 'to' + String get basename => fileSystem.path.basename(path); + + /// Gets the part of this entity's path before the last separator. + /// + /// context.dirname('path/to/foo.dart'); // -> 'path/to' + /// context.dirname('path/to'); // -> 'path' + /// context.dirname('foo.dart'); // -> '.' + /// + /// Trailing separators are ignored. + /// + /// context.dirname('path/to/'); // -> 'path' + String get dirname => fileSystem.path.dirname(path); + + // Override method definitions to codify the return type covariance. + @override + Future delete({bool recursive = false}); + + @override + Directory get parent; +} diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart new file mode 100644 index 000000000000..11a2d5a65d26 --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -0,0 +1,14 @@ +// Platform Implementation for Android +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +final class XFileAndroid extends XFilePlatform { + static void registerWith() { + XFilePlatform.instance = XFileAndroid(); + } + + @override + PlatformXFile createPlatformXFile(String path) { + // TODO: implement createPlatformXFile + throw UnimplementedError(); + } +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart new file mode 100644 index 000000000000..11315ed3770a --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart @@ -0,0 +1,563 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.0.5), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:io' show Platform; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} +/// Provides overrides for the constructors and static members of each +/// Dart proxy class. +/// +/// This is only intended to be used with unit tests to prevent errors from +/// making message calls in a unit test. +/// +/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. +@visibleForTesting +class PigeonOverrides { + /// Overrides [DocumentFile.fromSingleUri]. + static DocumentFile Function({required String path})? + documentFile_fromSingleUri; + + /// Sets all overridden ProxyApi class members to null. + static void pigeon_reset() { + documentFile_fromSingleUri = null; + } +} + +/// An immutable object that serves as the base class for all Dart proxy classes +/// and can provide functional copies of itself. +/// +/// All implementers are expected to be [immutable] as defined by the annotation +/// and override [pigeon_copy] returning an instance of itself. +@immutable +abstract class PigeonInternalProxyApiBaseClass { + /// Construct a [PigeonInternalProxyApiBaseClass]. + PigeonInternalProxyApiBaseClass({ + this.pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) : pigeon_instanceManager = + pigeon_instanceManager ?? PigeonInstanceManager.instance; + + /// Sends and receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used, which routes to + /// the host platform. + @protected + final BinaryMessenger? pigeon_binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final PigeonInstanceManager pigeon_instanceManager; + + /// Instantiates and returns a functionally identical object to oneself. + /// + /// Outside of tests, this method should only ever be called by + /// [PigeonInstanceManager]. + /// + /// Subclasses should always override their parent's implementation of this + /// method. + @protected + PigeonInternalProxyApiBaseClass pigeon_copy(); +} + +/// Maintains instances used to communicate with the native objects they +/// represent. +/// +/// Added instances are stored as weak references and their copies are stored +/// as strong references to maintain access to their variables and callback +/// methods. Both are stored with the same identifier. +/// +/// When a weak referenced instance becomes inaccessible, +/// [onWeakReferenceRemoved] is called with its associated identifier. +/// +/// If an instance is retrieved and has the possibility to be used, +/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference +/// is added as a weak reference with the same identifier. This prevents a +/// scenario where the weak referenced instance was released and then later +/// returned by the host platform. +class PigeonInstanceManager { + /// Constructs a [PigeonInstanceManager]. + PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { + this.onWeakReferenceRemoved = (int identifier) { + _weakInstances.remove(identifier); + onWeakReferenceRemoved(identifier); + }; + _finalizer = Finalizer(this.onWeakReferenceRemoved); + } + + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously by the host platform. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + static const int _maxDartCreatedIdentifier = 65536; + + /// The default [PigeonInstanceManager] used by Dart proxy classes. + /// + /// On creation, this manager makes a call to clear the native + /// InstanceManager. This is to prevent identifier conflicts after a host + /// restart. + static final PigeonInstanceManager instance = _initInstance(); + + // Expando is used because it doesn't prevent its keys from becoming + // inaccessible. This allows the manager to efficiently retrieve an identifier + // of an instance without holding a strong reference to that instance. + // + // It also doesn't use `==` to search for identifiers, which would lead to an + // infinite loop when comparing an object to its copy. (i.e. which was caused + // by calling instanceManager.getIdentifier() inside of `==` while this was a + // HashMap). + final Expando _identifiers = Expando(); + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; + late final Finalizer _finalizer; + int _nextIdentifier = 0; + + /// Called when a weak referenced instance is removed by [removeWeakReference] + /// or becomes inaccessible. + late final void Function(int) onWeakReferenceRemoved; + + static PigeonInstanceManager _initInstance() { + if (Platform.environment['FLUTTER_TEST'] == 'true') { + return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + } + WidgetsFlutterBinding.ensureInitialized(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. + api.clear(); + final PigeonInstanceManager instanceManager = PigeonInstanceManager( + onWeakReferenceRemoved: (int identifier) { + api.removeStrongReference(identifier); + }, + ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + return instanceManager; + } + + /// Adds a new instance that was instantiated by Dart. + /// + /// In other words, Dart wants to add a new instance that will represent + /// an object that will be instantiated on the host platform. + /// + /// Throws assertion error if the instance has already been added. + /// + /// Returns the randomly generated id of the [instance] added. + int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { + assert(getIdentifier(instance) == null); + + final int identifier = _nextUniqueIdentifier(); + _identifiers[instance] = identifier; + _weakInstances[identifier] = + WeakReference(instance); + _finalizer.attach(instance, identifier, detach: instance); + + final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); + _identifiers[copy] = identifier; + _strongInstances[identifier] = copy; + return identifier; + } + + /// Removes the instance, if present, and call [onWeakReferenceRemoved] with + /// its identifier. + /// + /// Returns the identifier associated with the removed instance. Otherwise, + /// `null` if the instance was not found in this manager. + /// + /// This does not remove the strong referenced instance associated with + /// [instance]. This can be done with [remove]. + int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { + final int? identifier = getIdentifier(instance); + if (identifier == null) { + return null; + } + + _identifiers[instance] = null; + _finalizer.detach(instance); + onWeakReferenceRemoved(identifier); + + return identifier; + } + + /// Removes [identifier] and its associated strongly referenced instance, if + /// present, from the manager. + /// + /// Returns the strong referenced instance associated with [identifier] before + /// it was removed. Returns `null` if [identifier] was not associated with + /// any strong reference. + /// + /// Throws an `AssertionError` if the weak referenced instance associated with + /// [identifier] is not removed first. This can be done with + /// [removeWeakReference]. + T? remove(int identifier) { + final T? instance = _weakInstances[identifier]?.target as T?; + assert( + instance == null, + 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', + ); + return _strongInstances.remove(identifier) as T?; + } + + /// Retrieves the instance associated with identifier. + /// + /// The value returned is chosen from the following order: + /// + /// 1. A weakly referenced instance associated with identifier. + /// 2. If the only instance associated with identifier is a strongly + /// referenced instance, a copy of the instance is added as a weak reference + /// with the same identifier. Returning the newly created copy. + /// 3. If no instance is associated with identifier, returns null. + /// + /// This method also expects the host `InstanceManager` to have a strong + /// reference to the instance the identifier is associated with. + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + + if (weakInstance == null) { + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + if (strongInstance != null) { + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + _identifiers[copy] = identifier; + _weakInstances[identifier] = WeakReference(copy); + _finalizer.attach(copy, identifier, detach: copy); + return copy as T; + } + return strongInstance as T?; + } + + return weakInstance as T; + } + + /// Retrieves the identifier associated with instance. + int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { + return _identifiers[instance]; + } + + /// Adds a new instance that was instantiated by the host platform. + /// + /// In other words, the host platform wants to add a new instance that + /// represents an object on the host platform. Stored with [identifier]. + /// + /// Throws assertion error if the instance or its identifier has already been + /// added. + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + assert(!containsIdentifier(identifier)); + assert(getIdentifier(instance) == null); + assert(identifier >= 0); + + _identifiers[instance] = identifier; + _strongInstances[identifier] = instance; + } + + /// Whether this manager contains the given [identifier]. + bool containsIdentifier(int identifier) { + return _weakInstances.containsKey(identifier) || + _strongInstances.containsKey(identifier); + } + + int _nextUniqueIdentifier() { + late int identifier; + do { + identifier = _nextIdentifier; + _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; + } while (containsIdentifier(identifier)); + return identifier; + } +} + +/// Generated API for managing the Dart and native `PigeonInstanceManager`s. +class _PigeonInternalInstanceManagerApi { + /// Constructor for [_PigeonInternalInstanceManagerApi]. + _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) + : pigeonVar_binaryMessenger = binaryMessenger; + + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + static void setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? binaryMessenger, + PigeonInstanceManager? instanceManager, + }) { + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + try { + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future removeStrongReference(int identifier) async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + /// Clear the native `PigeonInstanceManager`. + /// + /// This is typically called after a hot restart. + Future clear() async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } +} + +class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} + + + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} +class DocumentFile extends PigeonInternalProxyApiBaseClass { + factory DocumentFile.fromSingleUri({ + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + required String path, + }) { + if (PigeonOverrides.documentFile_fromSingleUri != null) { + return PigeonOverrides.documentFile_fromSingleUri!(path: path); + } + return DocumentFile.pigeon_fromSingleUri( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + path: path, + ); + } + + @protected + DocumentFile.pigeon_fromSingleUri({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required String path, + }) { + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier, path]); + () async { + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + } + + /// Constructs [DocumentFile] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + DocumentFile.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecDocumentFile = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + DocumentFile Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + DocumentFile pigeon_copy() { + return DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + diff --git a/packages/cross_file/cross_file_android/pigeons/copyright.txt b/packages/cross_file/cross_file_android/pigeons/copyright.txt new file mode 100644 index 000000000000..07e5f8598a80 --- /dev/null +++ b/packages/cross_file/cross_file_android/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/packages/cross_file/cross_file_android/pigeons/document_file.dart b/packages/cross_file/cross_file_android/pigeons/document_file.dart new file mode 100644 index 000000000000..caa118c9ff0d --- /dev/null +++ b/packages/cross_file/cross_file_android/pigeons/document_file.dart @@ -0,0 +1,21 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/document_file.g.dart', + kotlinOut: + 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt', + kotlinOptions: KotlinOptions( + package: 'dev.flutter.packages.cross_file_android', + ), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: 'androidx.documentfile.provider.DocumentFile', + ), +) +abstract class DocumentFile { + DocumentFile.fromSingleUri(String path); +} diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 123a1406c3ca..8ffb9e938da7 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -16,7 +16,7 @@ flutter: android: package: dev.flutter.packages.cross_file_android pluginClass: CrossFileAndroidPlugin - dartPluginClass: CrossFileAndroid + dartPluginClass: XFileAndroid dependencies: file: ^7.0.1 diff --git a/packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart b/packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart deleted file mode 100644 index 75db4051ba41..000000000000 --- a/packages/cross_file/cross_file_android/test/cross_file_android_method_channel_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_android/cross_file_android_method_channel.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - MethodChannelCrossFileAndroid platform = MethodChannelCrossFileAndroid(); - const MethodChannel channel = MethodChannel('cross_file_android'); - - setUp(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - channel, - (MethodCall methodCall) async { - return '42'; - }, - ); - }); - - tearDown(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null); - }); - - test('getPlatformVersion', () async { - expect(await platform.getPlatformVersion(), '42'); - }); -} diff --git a/packages/cross_file/cross_file_android/test/cross_file_android_test.dart b/packages/cross_file/cross_file_android/test/cross_file_android_test.dart deleted file mode 100644 index e7764d7e4407..000000000000 --- a/packages/cross_file/cross_file_android/test/cross_file_android_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_android/cross_file_android.dart'; -import 'package:cross_file_android/cross_file_android_platform_interface.dart'; -import 'package:cross_file_android/cross_file_android_method_channel.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -class MockCrossFileAndroidPlatform - with MockPlatformInterfaceMixin - implements CrossFileAndroidPlatform { - - @override - Future getPlatformVersion() => Future.value('42'); -} - -void main() { - final CrossFileAndroidPlatform initialPlatform = CrossFileAndroidPlatform.instance; - - test('$MethodChannelCrossFileAndroid is the default instance', () { - expect(initialPlatform, isInstanceOf()); - }); - - test('getPlatformVersion', () async { - CrossFileAndroid crossFileAndroidPlugin = CrossFileAndroid(); - MockCrossFileAndroidPlatform fakePlatform = MockCrossFileAndroidPlatform(); - CrossFileAndroidPlatform.instance = fakePlatform; - - expect(await crossFileAndroidPlugin.getPlatformVersion(), '42'); - }); -} diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index c734550d2c2f..91449d7fbf28 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -14,6 +14,8 @@ abstract base class PlatformXFile { final String path; + PlatformXFileExtension? get extension => null; + Future lastModified(); /// Reads the entire file contents as a list of bytes. @@ -25,5 +27,7 @@ abstract base class PlatformXFile { /// The length of the file. Future length(); - Stream openRead([int? start, int? end]); + Stream> openRead([int? start, int? end]); } + +mixin PlatformXFileExtension {} From e070cd3e66dcbdd2cece5a4d9ae18df350cc466c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Nov 2025 15:46:43 -0500 Subject: [PATCH 009/398] new interface --- .../lib/src/android_file.dart | 122 ++++++++++++++++++ .../lib/src/android_file_system.dart | 52 +++----- .../lib/src/android_file_system_entity.dart | 2 +- .../cross_file_android/pubspec.yaml | 1 + .../lib/cross_file_platform_interface.dart | 37 +----- .../lib/src/cross_file_platform.dart | 16 +++ .../lib/src/platform_cross_directory.dart | 37 ++++++ .../lib/src/platform_cross_file.dart | 62 +++++++++ ...atform_shared_storage_cross_directory.dart | 32 +++++ .../platform_shared_storage_cross_file.dart | 26 ++++ 10 files changed, 320 insertions(+), 67 deletions(-) create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_file.dart b/packages/cross_file/cross_file_android/lib/src/android_file.dart index 5e3a20c8d48d..eb6bd1fb69f9 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_file.dart @@ -290,3 +290,125 @@ base class AndroidFile extends PlatformXFile // TODO: implement writeAsStringSync } } + +class AFile with ForwardingFile { + @override + // TODO: implement absolute + File get absolute => throw UnimplementedError(); + + @override + // TODO: implement basename + String get basename => throw UnimplementedError(); + + @override + // TODO: implement delegate + io.File get delegate => throw UnimplementedError(); + + @override + Future delete({bool recursive = false}) { + // TODO: implement delete + throw UnimplementedError(); + } + + @override + void deleteSync({bool recursive = false}) { + // TODO: implement deleteSync + } + + @override + // TODO: implement dirname + String get dirname => throw UnimplementedError(); + + @override + Future exists() { + // TODO: implement exists + throw UnimplementedError(); + } + + @override + bool existsSync() { + // TODO: implement existsSync + throw UnimplementedError(); + } + + @override + // TODO: implement fileSystem + FileSystem get fileSystem => throw UnimplementedError(); + + @override + // TODO: implement isAbsolute + bool get isAbsolute => throw UnimplementedError(); + + @override + // TODO: implement parent + Directory get parent => throw UnimplementedError(); + + @override + // TODO: implement path + String get path => throw UnimplementedError(); + + @override + Future rename(String newPath) { + // TODO: implement rename + throw UnimplementedError(); + } + + @override + File renameSync(String newPath) { + // TODO: implement renameSync + throw UnimplementedError(); + } + + @override + Future resolveSymbolicLinks() { + // TODO: implement resolveSymbolicLinks + throw UnimplementedError(); + } + + @override + String resolveSymbolicLinksSync() { + // TODO: implement resolveSymbolicLinksSync + throw UnimplementedError(); + } + + @override + Future stat() { + // TODO: implement stat + throw UnimplementedError(); + } + + @override + io.FileStat statSync() { + // TODO: implement statSync + throw UnimplementedError(); + } + + @override + // TODO: implement uri + Uri get uri => throw UnimplementedError(); + + @override + Stream watch({int events = FileSystemEvent.all, bool recursive = false}) { + // TODO: implement watch + throw UnimplementedError(); + } + + @override + Directory wrapDirectory(io.Directory delegate) { + // TODO: implement wrapDirectory + throw UnimplementedError(); + } + + @override + File wrapFile(io.File delegate) { + // TODO: implement wrapFile + throw UnimplementedError(); + } + + @override + Link wrapLink(io.Link delegate) { + // TODO: implement wrapLink + throw UnimplementedError(); + } + +} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file_system.dart b/packages/cross_file/cross_file_android/lib/src/android_file_system.dart index a7fbbc005fe5..0012f8f03b46 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_file_system.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_file_system.dart @@ -1,13 +1,12 @@ import 'package:cross_file_android/src/document_file.g.dart'; import 'package:file/file.dart'; +import 'package:file/local.dart'; import 'package:path/src/context.dart'; +import 'dart:io' as io; class AndroidFileSystem extends FileSystem { const AndroidFileSystem(); - @override - Directory currentDirectory; - @override Directory directory(path) { throw UnimplementedError(); @@ -19,53 +18,40 @@ class AndroidFileSystem extends FileSystem { } @override - Future identical(String path1, String path2) { - // TODO: implement identical - throw UnimplementedError(); - } + Future identical(String path1, String path2) => + throw UnimplementedError(); @override - bool identicalSync(String path1, String path2) { - // TODO: implement identicalSync - throw UnimplementedError(); - } + bool identicalSync(String path1, String path2) => throw UnimplementedError(); + + @override + bool get isWatchSupported => false; @override - // TODO: implement isWatchSupported - bool get isWatchSupported => throw UnimplementedError(); + Link link(path) => throw UnimplementedError(); @override - Link link(path) { - // TODO: implement link + Future stat(String path) { throw UnimplementedError(); } @override - // TODO: implement path - Context get path => throw UnimplementedError(); + FileStat statSync(String path) => throw UnimplementedError(); @override - Future stat(String path) { - // TODO: implement stat - throw UnimplementedError(); - } + Future type(String path, {bool followLinks = true}) => throw UnimplementedError(); @override - FileStat statSync(String path) { - throw UnimplementedError(); - } + FileSystemEntityType typeSync(String path, {bool followLinks = true}) => throw UnimplementedError(); @override - Directory get systemTempDirectory => throw UnimplementedError(); + Directory currentDirectory => throw UnimplementedError(); @override - Future type(String path, {bool followLinks = true}) { - throw UnimplementedError(); - } + // TODO: implement path + Context get path => Context(); @override - FileSystemEntityType typeSync(String path, {bool followLinks = true}) { - throw UnimplementedError(); - } - -} \ No newline at end of file + // TODO: implement systemTempDirectory + Directory get systemTempDirectory => File.systemTempDirectory; +} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart b/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart index e3080cbf6dad..2729f5b271f3 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart @@ -5,7 +5,7 @@ import 'package:file/file.dart'; import 'android_file_system.dart'; -mixin AndroidFileSystemEntity implements FileSystemEntity { +mixin AndroidFileSystemEntity on FileSystemEntity { DocumentFile get nativeFile; /// Returns the file system responsible for this entity. diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 8ffb9e938da7..ce31800c1177 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -24,6 +24,7 @@ dependencies: sdk: flutter cross_file_platform_interface: path: ../cross_file_platform_interface + path: ^1.9.1 dev_dependencies: flutter_test: diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index 91449d7fbf28..8bc4460ed05d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -1,33 +1,4 @@ -// Platform Interface - -import 'dart:convert'; -import 'dart:typed_data'; - -abstract base class XFilePlatform { - static XFilePlatform? instance; - - PlatformXFile createPlatformXFile(String path); -} - -abstract base class PlatformXFile { - PlatformXFile(this.path); - - final String path; - - PlatformXFileExtension? get extension => null; - - Future lastModified(); - - /// Reads the entire file contents as a list of bytes. - Future readAsBytes(); - - /// Reads the entire file contents as a string using the given Encoding. - Future readAsString({Encoding encoding = utf8}); - - /// The length of the file. - Future length(); - - Stream> openRead([int? start, int? end]); -} - -mixin PlatformXFileExtension {} +export 'src/cross_file_platform.dart'; +export 'src/platform_cross_directory.dart'; +export 'src/platform_cross_file.dart'; +export 'src/shared_storage/platform_shared_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart new file mode 100644 index 000000000000..681ce9a7a2a9 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -0,0 +1,16 @@ +import 'platform_cross_directory.dart'; +import 'platform_cross_file.dart'; + +abstract base class CrossFilePlatform { + static CrossFilePlatform? instance; + + PlatformXFile createPlatformXFile(PlatformXFileCreationParams params); + + PlatformXDirectory createPlatformXDirectory( + PlatformXDirectoryCreationParams params, + ) { + throw UnimplementedError( + 'createPlatformXDirectory is not implemented on the current platform.', + ); + } +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart new file mode 100644 index 000000000000..c7452ba71656 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -0,0 +1,37 @@ +import 'package:flutter/foundation.dart'; + +import 'cross_file_platform.dart'; + +@immutable +base class PlatformXDirectoryCreationParams { + const PlatformXDirectoryCreationParams({required this.path}); + + final String path; +} + +mixin PlatformXDirectoryExtension {} + +abstract base class PlatformXDirectory { + /// Creates a new [PlatformXDirectory] + factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { + assert( + CrossFilePlatform.instance != null, + 'A platform implementation for `cross_file` has not been set. Please ' + 'ensure that an implementation of `CrossFilePlatform` has been set to ' + '`CrossFilePlatform.instance` before use. For unit testing, ' + '`CrossFilePlatform.instance` can be set with your own test implementation.', + ); + final PlatformXDirectory file = CrossFilePlatform.instance! + .createPlatformXDirectory(params); + return file; + } + + @protected + PlatformXDirectory.implementation(this.params); + + final PlatformXDirectoryCreationParams params; + + PlatformXDirectoryExtension? get extension => null; + + Future exists(); +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart new file mode 100644 index 000000000000..dd853f91d2dc --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -0,0 +1,62 @@ +import 'dart:convert'; + +import 'package:flutter/foundation.dart'; + +import 'cross_file_platform.dart'; + +@immutable +base class PlatformXFileCreationParams { + const PlatformXFileCreationParams({required this.path}); + + final String path; +} + +mixin PlatformXFileExtension {} + +abstract base class PlatformXFile { + /// Creates a new [PlatformXFile] + factory PlatformXFile(PlatformXFileCreationParams params) { + assert( + CrossFilePlatform.instance != null, + 'A platform implementation for `cross_file` has not been set. Please ' + 'ensure that an implementation of `XFilePlatform` has been set to ' + '`CrossFilePlatform.instance` before use. For unit testing, ' + '`CrossFilePlatform.instance` can be set with your own test implementation.', + ); + final PlatformXFile file = CrossFilePlatform.instance!.createPlatformXFile( + params, + ); + return file; + } + + @protected + PlatformXFile.implementation(this.params); + + final PlatformXFileCreationParams params; + + PlatformXFileExtension? get extension => null; + + Future lastModified(); + + /// The length of the file. + Future length(); + + /// Whether file exists. + Future exists(); + + Future canRead(); + + Stream> openRead([int? start, int? end]) { + throw UnimplementedError(); + } + + /// Reads the entire file contents as a list of bytes. + Future readAsBytes() { + throw UnimplementedError(); + } + + /// Reads the entire file contents as a string using the given Encoding. + Future readAsString({Encoding encoding = utf8}) { + throw UnimplementedError(); + } +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart new file mode 100644 index 000000000000..d77542ae9f94 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart @@ -0,0 +1,32 @@ +import 'package:flutter/foundation.dart'; + +import '../../cross_file_platform_interface.dart'; + +@immutable +base class PlatformSharedStorageXDirectoryCreationParams + extends PlatformXDirectoryCreationParams { + const PlatformSharedStorageXDirectoryCreationParams({required super.path}); +} + +mixin SharedStoragePlatformXDirectoryExtension + implements PlatformXDirectoryExtension {} + +abstract base class PlatformSharedStorageXDirectory extends PlatformXDirectory { + PlatformSharedStorageXDirectory( + PlatformSharedStorageXDirectoryCreationParams params, + ) : super.implementation(params); + + @override + PlatformSharedStorageXDirectoryCreationParams get params => + super.params as PlatformSharedStorageXDirectoryCreationParams; + + @override + SharedStoragePlatformXDirectoryExtension? get extension => + super.extension as SharedStoragePlatformXDirectoryExtension?; + + Future listFiles(ListFileParams params); +} + +class ListFileParams { + +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart new file mode 100644 index 000000000000..bcff9589bdd9 --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart @@ -0,0 +1,26 @@ +import 'package:flutter/foundation.dart'; + +import '../../cross_file_platform_interface.dart'; + +@immutable +base class PlatformSharedStorageXFileCreationParams + extends PlatformXFileCreationParams { + const PlatformSharedStorageXFileCreationParams({required super.path}); +} + +mixin SharedStoragePlatformXFileExtension implements PlatformXFileExtension {} + +abstract base class PlatformSharedStorageXFile extends PlatformXFile { + PlatformSharedStorageXFile(PlatformSharedStorageXFileCreationParams params) + : super.implementation(params); + + @override + PlatformSharedStorageXFileCreationParams get params => + super.params as PlatformSharedStorageXFileCreationParams; + + @override + SharedStoragePlatformXFileExtension? get extension => + super.extension as SharedStoragePlatformXFileExtension?; + + Future delete(); +} From 191eea14017ef9e2b87aeb2b06a685dcafcfdd6f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Nov 2025 15:53:58 -0500 Subject: [PATCH 010/398] update android with base implemenation --- .../lib/cross_file_android.dart | 22 +- .../lib/src/android_cross_file.dart | 21 +- .../lib/src/android_cross_file_extension.dart | 5 - .../lib/src/android_file.dart | 414 ------------------ .../lib/src/android_file_system.dart | 57 --- .../lib/src/android_file_system_entity.dart | 41 -- .../lib/src/cross_file_android.dart | 13 +- .../cross_file_android/pubspec.yaml | 2 - 8 files changed, 36 insertions(+), 539 deletions(-) delete mode 100644 packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart delete mode 100644 packages/cross_file/cross_file_android/lib/src/android_file.dart delete mode 100644 packages/cross_file/cross_file_android/lib/src/android_file_system.dart delete mode 100644 packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 3912d8b994b9..25b266cef32d 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -3,15 +3,9 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:file/file.dart'; -base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { - AndroidXFile(super.path); - - @override - PlatformXFileExtension? get extension { - return this; - } +base class AndroidXFile extends PlatformXFile { + AndroidXFile(super.path) : super.implementation(); @override Future lastModified() { @@ -42,4 +36,16 @@ base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { // TODO: implement readAsString throw UnimplementedError(); } + + @override + Future canRead() { + // TODO: implement canRead + throw UnimplementedError(); + } + + @override + Future exists() { + // TODO: implement exists + throw UnimplementedError(); + } } diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index 0ba43fb31d8f..72792e3c55c1 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -1,13 +1,10 @@ import 'dart:convert'; import 'dart:typed_data'; -base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { - AndroidXFile(super.path); +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; - @override - PlatformXFileExtension? get extension { - return this; - } +base class AndroidXFile extends PlatformXFile { + AndroidXFile(super.params) : super.implementation(); @override Future lastModified() { @@ -38,4 +35,16 @@ base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { // TODO: implement readAsString throw UnimplementedError(); } + + @override + Future canRead() { + // TODO: implement canRead + throw UnimplementedError(); + } + + @override + Future exists() { + // TODO: implement exists + throw UnimplementedError(); + } } \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart deleted file mode 100644 index c3a13880fcf1..000000000000 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file_extension.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; - -mixin AndroidXFileExtension implements PlatformXFileExtension { - -} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file.dart b/packages/cross_file/cross_file_android/lib/src/android_file.dart deleted file mode 100644 index eb6bd1fb69f9..000000000000 --- a/packages/cross_file/cross_file_android/lib/src/android_file.dart +++ /dev/null @@ -1,414 +0,0 @@ -import 'dart:convert'; - -import 'dart:typed_data'; - -import 'dart:io' as io; - -import 'package:cross_file_android/src/android_file_system.dart'; -import 'package:cross_file_android/src/android_file_system_entity.dart'; -import 'package:cross_file_android/src/document_file.g.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:file/file.dart'; - -base class AndroidFile extends PlatformXFile - with AndroidFileSystemEntity - implements File { - AndroidFile(super.path) - : _documentFile = DocumentFile.fromSingleUri(path: path); - - DocumentFile _documentFile; - - @override - File get absolute => fileSystem.file(path); - - @override - Future copy(String newPath) { - // TODO: implement copy - throw UnimplementedError(); - } - - @override - File copySync(String newPath) { - // TODO: implement copySync - throw UnimplementedError(); - } - - @override - Future create({bool recursive = false, bool exclusive = false}) { - // TODO: implement create - throw UnimplementedError(); - } - - @override - void createSync({bool recursive = false, bool exclusive = false}) { - // TODO: implement createSync - } - - @override - Future delete({bool recursive = false}) { - // TODO: implement delete - throw UnimplementedError(); - } - - @override - void deleteSync({bool recursive = false}) { - // TODO: implement deleteSync - } - - @override - // TODO: implement dirname - String get dirname => throw UnimplementedError(); - - @override - Future exists() { - // TODO: implement exists - throw UnimplementedError(); - } - - @override - bool existsSync() { - // TODO: implement existsSync - throw UnimplementedError(); - } - - @override - // TODO: implement isAbsolute - bool get isAbsolute => throw UnimplementedError(); - - @override - Future lastAccessed() { - // TODO: implement lastAccessed - throw UnimplementedError(); - } - - @override - DateTime lastAccessedSync() { - // TODO: implement lastAccessedSync - throw UnimplementedError(); - } - - @override - Future lastModified() { - // TODO: implement lastModified - throw UnimplementedError(); - } - - @override - DateTime lastModifiedSync() { - // TODO: implement lastModifiedSync - throw UnimplementedError(); - } - - @override - Future length() { - // TODO: implement length - throw UnimplementedError(); - } - - @override - int lengthSync() { - // TODO: implement lengthSync - throw UnimplementedError(); - } - - @override - Future open({FileMode mode = FileMode.read}) { - // TODO: implement open - throw UnimplementedError(); - } - - @override - Stream> openRead([int? start, int? end]) { - // TODO: implement openRead - throw UnimplementedError(); - } - - @override - RandomAccessFile openSync({FileMode mode = FileMode.read}) { - // TODO: implement openSync - throw UnimplementedError(); - } - - @override - IOSink openWrite({FileMode mode = FileMode.write, Encoding encoding = utf8}) { - // TODO: implement openWrite - throw UnimplementedError(); - } - - @override - // TODO: implement parent - Directory get parent => throw UnimplementedError(); - - @override - // TODO: implement path - String get path => throw UnimplementedError(); - - @override - Future readAsBytes() { - // TODO: implement readAsBytes - throw UnimplementedError(); - } - - @override - Uint8List readAsBytesSync() { - // TODO: implement readAsBytesSync - throw UnimplementedError(); - } - - @override - Future> readAsLines({Encoding encoding = utf8}) { - // TODO: implement readAsLines - throw UnimplementedError(); - } - - @override - List readAsLinesSync({Encoding encoding = utf8}) { - // TODO: implement readAsLinesSync - throw UnimplementedError(); - } - - @override - Future readAsString({Encoding encoding = utf8}) { - // TODO: implement readAsString - throw UnimplementedError(); - } - - @override - String readAsStringSync({Encoding encoding = utf8}) { - // TODO: implement readAsStringSync - throw UnimplementedError(); - } - - @override - Future rename(String newPath) { - // TODO: implement rename - throw UnimplementedError(); - } - - @override - File renameSync(String newPath) { - // TODO: implement renameSync - throw UnimplementedError(); - } - - @override - Future resolveSymbolicLinks() { - // TODO: implement resolveSymbolicLinks - throw UnimplementedError(); - } - - @override - String resolveSymbolicLinksSync() { - // TODO: implement resolveSymbolicLinksSync - throw UnimplementedError(); - } - - @override - Future setLastAccessed(DateTime time) { - // TODO: implement setLastAccessed - throw UnimplementedError(); - } - - @override - void setLastAccessedSync(DateTime time) { - // TODO: implement setLastAccessedSync - } - - @override - Future setLastModified(DateTime time) { - // TODO: implement setLastModified - throw UnimplementedError(); - } - - @override - void setLastModifiedSync(DateTime time) { - // TODO: implement setLastModifiedSync - } - - @override - Future stat() { - // TODO: implement stat - throw UnimplementedError(); - } - - @override - FileStat statSync() { - // TODO: implement statSync - throw UnimplementedError(); - } - - @override - // TODO: implement uri - Uri get uri => throw UnimplementedError(); - - @override - Stream watch({ - int events = FileSystemEvent.all, - bool recursive = false, - }) { - // TODO: implement watch - throw UnimplementedError(); - } - - @override - Future writeAsBytes( - List bytes, { - FileMode mode = io.FileMode.write, - bool flush = false, - }) { - // TODO: implement writeAsBytes - throw UnimplementedError(); - } - - @override - void writeAsBytesSync( - List bytes, { - FileMode mode = FileMode.write, - bool flush = false, - }) { - // TODO: implement writeAsBytesSync - } - - @override - Future writeAsString( - String contents, { - FileMode mode = io.FileMode.write, - Encoding encoding = utf8, - bool flush = false, - }) { - // TODO: implement writeAsString - throw UnimplementedError(); - } - - @override - void writeAsStringSync( - String contents, { - FileMode mode = FileMode.write, - Encoding encoding = utf8, - bool flush = false, - }) { - // TODO: implement writeAsStringSync - } -} - -class AFile with ForwardingFile { - @override - // TODO: implement absolute - File get absolute => throw UnimplementedError(); - - @override - // TODO: implement basename - String get basename => throw UnimplementedError(); - - @override - // TODO: implement delegate - io.File get delegate => throw UnimplementedError(); - - @override - Future delete({bool recursive = false}) { - // TODO: implement delete - throw UnimplementedError(); - } - - @override - void deleteSync({bool recursive = false}) { - // TODO: implement deleteSync - } - - @override - // TODO: implement dirname - String get dirname => throw UnimplementedError(); - - @override - Future exists() { - // TODO: implement exists - throw UnimplementedError(); - } - - @override - bool existsSync() { - // TODO: implement existsSync - throw UnimplementedError(); - } - - @override - // TODO: implement fileSystem - FileSystem get fileSystem => throw UnimplementedError(); - - @override - // TODO: implement isAbsolute - bool get isAbsolute => throw UnimplementedError(); - - @override - // TODO: implement parent - Directory get parent => throw UnimplementedError(); - - @override - // TODO: implement path - String get path => throw UnimplementedError(); - - @override - Future rename(String newPath) { - // TODO: implement rename - throw UnimplementedError(); - } - - @override - File renameSync(String newPath) { - // TODO: implement renameSync - throw UnimplementedError(); - } - - @override - Future resolveSymbolicLinks() { - // TODO: implement resolveSymbolicLinks - throw UnimplementedError(); - } - - @override - String resolveSymbolicLinksSync() { - // TODO: implement resolveSymbolicLinksSync - throw UnimplementedError(); - } - - @override - Future stat() { - // TODO: implement stat - throw UnimplementedError(); - } - - @override - io.FileStat statSync() { - // TODO: implement statSync - throw UnimplementedError(); - } - - @override - // TODO: implement uri - Uri get uri => throw UnimplementedError(); - - @override - Stream watch({int events = FileSystemEvent.all, bool recursive = false}) { - // TODO: implement watch - throw UnimplementedError(); - } - - @override - Directory wrapDirectory(io.Directory delegate) { - // TODO: implement wrapDirectory - throw UnimplementedError(); - } - - @override - File wrapFile(io.File delegate) { - // TODO: implement wrapFile - throw UnimplementedError(); - } - - @override - Link wrapLink(io.Link delegate) { - // TODO: implement wrapLink - throw UnimplementedError(); - } - -} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file_system.dart b/packages/cross_file/cross_file_android/lib/src/android_file_system.dart deleted file mode 100644 index 0012f8f03b46..000000000000 --- a/packages/cross_file/cross_file_android/lib/src/android_file_system.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:cross_file_android/src/document_file.g.dart'; -import 'package:file/file.dart'; -import 'package:file/local.dart'; -import 'package:path/src/context.dart'; -import 'dart:io' as io; - -class AndroidFileSystem extends FileSystem { - const AndroidFileSystem(); - - @override - Directory directory(path) { - throw UnimplementedError(); - } - - @override - File file(path) { - throw UnimplementedError(); - } - - @override - Future identical(String path1, String path2) => - throw UnimplementedError(); - - @override - bool identicalSync(String path1, String path2) => throw UnimplementedError(); - - @override - bool get isWatchSupported => false; - - @override - Link link(path) => throw UnimplementedError(); - - @override - Future stat(String path) { - throw UnimplementedError(); - } - - @override - FileStat statSync(String path) => throw UnimplementedError(); - - @override - Future type(String path, {bool followLinks = true}) => throw UnimplementedError(); - - @override - FileSystemEntityType typeSync(String path, {bool followLinks = true}) => throw UnimplementedError(); - - @override - Directory currentDirectory => throw UnimplementedError(); - - @override - // TODO: implement path - Context get path => Context(); - - @override - // TODO: implement systemTempDirectory - Directory get systemTempDirectory => File.systemTempDirectory; -} diff --git a/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart b/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart deleted file mode 100644 index 2729f5b271f3..000000000000 --- a/packages/cross_file/cross_file_android/lib/src/android_file_system_entity.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'dart:io' as io; - -import 'package:cross_file_android/src/document_file.g.dart'; -import 'package:file/file.dart'; - -import 'android_file_system.dart'; - -mixin AndroidFileSystemEntity on FileSystemEntity { - DocumentFile get nativeFile; - - /// Returns the file system responsible for this entity. - FileSystem get fileSystem => const AndroidFileSystem(); - - /// Gets the part of this entity's path after the last separator. - /// - /// context.basename('path/to/foo.dart'); // -> 'foo.dart' - /// context.basename('path/to'); // -> 'to' - /// - /// Trailing separators are ignored. - /// - /// context.basename('path/to/'); // -> 'to' - String get basename => fileSystem.path.basename(path); - - /// Gets the part of this entity's path before the last separator. - /// - /// context.dirname('path/to/foo.dart'); // -> 'path/to' - /// context.dirname('path/to'); // -> 'path' - /// context.dirname('foo.dart'); // -> '.' - /// - /// Trailing separators are ignored. - /// - /// context.dirname('path/to/'); // -> 'path' - String get dirname => fileSystem.path.dirname(path); - - // Override method definitions to codify the return type covariance. - @override - Future delete({bool recursive = false}); - - @override - Directory get parent; -} diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index 11a2d5a65d26..b8aa7a205951 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -1,14 +1,15 @@ // Platform Implementation for Android import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -final class XFileAndroid extends XFilePlatform { +import '../cross_file_android.dart'; + +final class CrossFileAndroid extends CrossFilePlatform { static void registerWith() { - XFilePlatform.instance = XFileAndroid(); + CrossFilePlatform.instance = CrossFileAndroid(); } @override - PlatformXFile createPlatformXFile(String path) { - // TODO: implement createPlatformXFile - throw UnimplementedError(); + AndroidXFile createPlatformXFile(PlatformXFileCreationParams params) { + return AndroidXFile(params); } -} \ No newline at end of file +} diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index ce31800c1177..bb734c544826 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -19,12 +19,10 @@ flutter: dartPluginClass: XFileAndroid dependencies: - file: ^7.0.1 flutter: sdk: flutter cross_file_platform_interface: path: ../cross_file_platform_interface - path: ^1.9.1 dev_dependencies: flutter_test: From a9c4202f958654402bb47b66714592cf96550493 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:37:40 -0500 Subject: [PATCH 011/398] start of impl --- .../{ => proxies}/DocumentFile.g.kt | 339 ++++++++++- .../lib/src/android_cross_file.dart | 51 +- .../lib/src/document_file.g.dart | 554 ++++++++++++++++++ .../pigeons/document_file.dart | 48 +- 4 files changed, 967 insertions(+), 25 deletions(-) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/{ => proxies}/DocumentFile.g.kt (57%) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt similarity index 57% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt index 99c347839ad1..d43b6d84f12b 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt @@ -5,7 +5,7 @@ // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") -package dev.flutter.packages.cross_file_android +package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel @@ -405,13 +405,35 @@ abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMe */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile + /** + * An implementation of [PigeonApiContentResolver] used to add a new Dart instance of + * `ContentResolver` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiContentResolver(): PigeonApiContentResolver + + /** + * An implementation of [PigeonApiInputStreamReadBytesResponse] used to add a new Dart instance of + * `InputStreamReadBytesResponse` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse + + /** + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of + * `InputStream` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiInputStream(): PigeonApiInputStream + fun setUp() { DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, instanceManager) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, getPigeonApiDocumentFile()) + PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) + PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } fun tearDown() { DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) + PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, null) + PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePigeonProxyApiRegistrar) : DocumentFilePigeonCodec() { @@ -452,6 +474,27 @@ private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePig } } } + else if (value is android.content.ContentResolver) { + registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) + } + } + } + else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) + } + } + } + else if (value is java.io.InputStream) { + registrar.getPigeonApiInputStream().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) + } + } + } when { registrar.instanceManager.containsInstance(value) -> { @@ -475,6 +518,16 @@ private open class DocumentFilePigeonCodec : StandardMessageCodec() { abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { abstract fun fromSingleUri(path: String): androidx.documentfile.provider.DocumentFile + abstract fun canRead(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + abstract fun delete(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long + + abstract fun length(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long + companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { @@ -498,6 +551,91 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } @@ -532,3 +670,202 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } +/** https://developer.android.com/reference/kotlin/android/content/ContentResolver */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { + abstract fun instance(): android.content.ContentResolver + + abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { + val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0] as Long + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as android.content.ContentResolver + val uriArg = args[1] as String + val wrapped: List = try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { + abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long + + abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val returnValueArg = returnValue(pigeon_instanceArg) + val bytesArg = bytes(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { + abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + + abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { + val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as java.io.InputStream + val lenArg = args[1] as Long + val wrapped: List = try { + listOf(api.readBytes(pigeon_instanceArg, lenArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as java.io.InputStream + val wrapped: List = try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index 72792e3c55c1..0b43081d73ad 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -1,33 +1,46 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:cross_file_android/src/document_file.g.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; base class AndroidXFile extends PlatformXFile { AndroidXFile(super.params) : super.implementation(); + late final DocumentFile _documentFile = DocumentFile.fromSingleUri( + path: params.path, + ); + + late final ContentResolver _contentResolver = ContentResolver.instance; + @override - Future lastModified() { - // TODO: implement lastModified - throw UnimplementedError(); + Future lastModified() async { + return DateTime.fromMillisecondsSinceEpoch( + await _documentFile.lastModified(), + ); } @override - Future length() { - // TODO: implement length - throw UnimplementedError(); - } + Future length() => _documentFile.length(); @override - Stream openRead([int? start, int? end]) { - // TODO: implement openRead - throw UnimplementedError(); + Stream openRead([int? start, int? end]) async* { + final InputStream inputStream = await _contentResolver.openInputStream( + params.path, + ); + InputStreamReadBytesResponse response = await inputStream.readBytes(1024); + while(response.returnValue != -1) { + yield response.bytes; + response = await inputStream.readBytes(1024); + } } @override - Future readAsBytes() { - // TODO: implement readAsBytes - throw UnimplementedError(); + Future readAsBytes() async { + final InputStream inputStream = await _contentResolver.openInputStream( + params.path, + ); + return inputStream.readAllBytes(); } @override @@ -37,14 +50,8 @@ base class AndroidXFile extends PlatformXFile { } @override - Future canRead() { - // TODO: implement canRead - throw UnimplementedError(); - } + Future canRead() => _documentFile.canRead(); @override - Future exists() { - // TODO: implement exists - throw UnimplementedError(); - } -} \ No newline at end of file + Future exists() => _documentFile.exists(); +} diff --git a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart index 11315ed3770a..5e7cf559a9e6 100644 --- a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart @@ -42,9 +42,13 @@ class PigeonOverrides { static DocumentFile Function({required String path})? documentFile_fromSingleUri; + /// Overrides [ContentResolver.instance]. + static ContentResolver? contentResolver_instance; + /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { documentFile_fromSingleUri = null; + contentResolver_instance = null; } } @@ -155,6 +159,9 @@ class PigeonInstanceManager { ); _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -552,6 +559,176 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + Future canRead() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.canRead'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future delete() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.delete'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future exists() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.exists'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future lastModified() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as int?)!; + } + } + + Future length() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.length'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as int?)!; + } + } + @override DocumentFile pigeon_copy() { return DocumentFile.pigeon_detached( @@ -561,3 +738,380 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } +/// https://developer.android.com/reference/kotlin/android/content/ContentResolver +class ContentResolver extends PigeonInternalProxyApiBaseClass { + /// Constructs [ContentResolver] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + ContentResolver.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecContentResolver = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static final ContentResolver _instance = pigeonVar_instance(); + + static ContentResolver get instance => + PigeonOverrides.contentResolver_instance ?? _instance; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + ContentResolver Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + static ContentResolver pigeonVar_instance() { + final ContentResolver pigeonVar_instance = + ContentResolver.pigeon_detached(); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); + final BinaryMessenger pigeonVar_binaryMessenger = + ServicesBinding.instance.defaultBinaryMessenger; + final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance + .addDartCreatedInstance(pigeonVar_instance); + () async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.ContentResolver.instance'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + return pigeonVar_instance; + } + + Future openInputStream(String uri) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecContentResolver; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, uri]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as InputStream?)!; + } + } + + @override + ContentResolver pigeon_copy() { + return ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { + /// Constructs [InputStreamReadBytesResponse] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + InputStreamReadBytesResponse.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.returnValue, + required this.bytes, + }); + + final int returnValue; + + final Uint8List bytes; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + InputStreamReadBytesResponse Function( + int returnValue, + Uint8List bytes, + )? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + final int? arg_returnValue = (args[1] as int?); + assert(arg_returnValue != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + final Uint8List? arg_bytes = (args[2] as Uint8List?); + assert(arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: arg_returnValue!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + InputStreamReadBytesResponse pigeon_copy() { + return InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: returnValue, + bytes: bytes, + ); + } +} + +class InputStream extends PigeonInternalProxyApiBaseClass { + /// Constructs [InputStream] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + InputStream.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecInputStream = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + InputStream Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future readBytes(int len) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecInputStream; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.InputStream.readBytes'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, len]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as InputStreamReadBytesResponse?)!; + } + } + + Future readAllBytes() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecInputStream; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as Uint8List?)!; + } + } + + @override + InputStream pigeon_copy() { + return InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + diff --git a/packages/cross_file/cross_file_android/pigeons/document_file.dart b/packages/cross_file/cross_file_android/pigeons/document_file.dart index caa118c9ff0d..aef07ae0921f 100644 --- a/packages/cross_file/cross_file_android/pigeons/document_file.dart +++ b/packages/cross_file/cross_file_android/pigeons/document_file.dart @@ -4,9 +4,9 @@ import 'package:pigeon/pigeon.dart'; PigeonOptions( dartOut: 'lib/src/document_file.g.dart', kotlinOut: - 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/DocumentFile.g.kt', + 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt', kotlinOptions: KotlinOptions( - package: 'dev.flutter.packages.cross_file_android', + package: 'dev.flutter.packages.cross_file_android.proxies', ), copyrightHeader: 'pigeons/copyright.txt', ), @@ -18,4 +18,48 @@ import 'package:pigeon/pigeon.dart'; ) abstract class DocumentFile { DocumentFile.fromSingleUri(String path); + + bool canRead(); + + bool delete(); + + bool exists(); + + int lastModified(); + + int length(); +} + +/// https://developer.android.com/reference/kotlin/android/content/ContentResolver +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: 'android.content.ContentResolver', + ), +) +abstract class ContentResolver { + @static + late final ContentResolver instance; + + InputStream openInputStream(String uri); +} + +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: + 'dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse', + ), +) +abstract class InputStreamReadBytesResponse { + late final int returnValue; + + late final Uint8List bytes; +} + +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), +) +abstract class InputStream { + InputStreamReadBytesResponse readBytes(int len); + + Uint8List readAllBytes(); } From 6aa763ea8416727453bb5caac81e5a7db4e6c372 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 14 Nov 2025 17:12:58 -0500 Subject: [PATCH 012/398] implementation of pigeon --- .../CrossFileAndroidPlugin.kt | 30 +- .../InputStreamReadBytesResponse.kt | 21 + .../cross_file_android/ProxyApiRegistrar.kt | 53 +++ .../proxies/ContentResolverProxyApi.kt | 26 ++ .../proxies/DocumentFile.g.kt | 379 +++++++++++++++++- .../proxies/DocumentFileProxyApi.kt | 43 ++ .../proxies/InputStreamProxyApi.kt | 31 ++ .../InputStreamReadBytesResponseProxyApi.kt | 26 ++ .../proxies/ContentResolverTest.kt | 32 ++ .../proxies/DocumentFileTest.kt | 81 ++++ .../InputStreamReadBytesResponseTest.kt | 41 ++ .../proxies/InputStreamTest.kt | 43 ++ .../cross_file_android/example/lib/main.dart | 28 -- .../lib/cross_file_android.dart | 53 +-- .../lib/src/android_cross_file.dart | 33 +- .../lib/src/document_file.g.dart | 45 ++- .../pigeons/document_file.dart | 4 +- .../cross_file_android/pubspec.yaml | 4 +- 18 files changed, 851 insertions(+), 122 deletions(-) create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt index 66090e265674..076091bad3c0 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt @@ -8,31 +8,19 @@ import io.flutter.plugin.common.MethodChannel.Result /** CrossFileAndroidPlugin */ class CrossFileAndroidPlugin : - FlutterPlugin, - MethodCallHandler { - // The MethodChannel that will the communication between Flutter and native Android - // - // This local reference serves to register the plugin with the Flutter Engine and unregister it - // when the Flutter Engine is detached from the Activity - private lateinit var channel: MethodChannel + FlutterPlugin { - override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cross_file_android") - channel.setMethodCallHandler(this) - } + private lateinit var registrar: ProxyApiRegistrar - override fun onMethodCall( - call: MethodCall, - result: Result - ) { - if (call.method == "getPlatformVersion") { - result.success("Android ${android.os.Build.VERSION.RELEASE}") - } else { - result.notImplemented() - } + override fun onAttachedToEngine(pluginBinding: FlutterPlugin.FlutterPluginBinding) { + registrar = + ProxyApiRegistrar(pluginBinding.binaryMessenger, context = pluginBinding.applicationContext) + registrar.setUp() } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - channel.setMethodCallHandler(null) + registrar.ignoreCallsToDart = true + registrar.tearDown() + registrar.instanceManager.clear() } } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt new file mode 100644 index 000000000000..3b552f0fd26f --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt @@ -0,0 +1,21 @@ +package dev.flutter.packages.cross_file_android + +data class InputStreamReadBytesResponse(val returnValue: Int, val bytes: ByteArray) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as InputStreamReadBytesResponse + + if (returnValue != other.returnValue) return false + if (!bytes.contentEquals(other.bytes)) return false + + return true + } + + override fun hashCode(): Int { + var result = returnValue + result = 31 * result + bytes.contentHashCode() + return result + } +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt new file mode 100644 index 000000000000..2ba65081feea --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -0,0 +1,53 @@ +package dev.flutter.packages.cross_file_android + +import android.content.Context +import android.os.Build +import android.os.Looper +import androidx.annotation.ChecksSdkIntAtLeast +import dev.flutter.packages.cross_file_android.proxies.DocumentFilePigeonProxyApiRegistrar +import dev.flutter.packages.cross_file_android.proxies.PigeonApiContentResolver +import dev.flutter.packages.cross_file_android.proxies.PigeonApiDocumentFile +import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStream +import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStreamReadBytesResponse +import io.flutter.plugin.common.BinaryMessenger +import android.os.Handler +import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi +import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi +import dev.flutter.packages.cross_file_android.proxies.InputStreamProxyApi +import dev.flutter.packages.cross_file_android.proxies.InputStreamReadBytesResponseProxyApi + +/** + * Implementation of [InteractiveMediaAdsLibraryPigeonProxyApiRegistrar] that provides each ProxyApi + * implementation and any additional resources needed by an implementation. + */ +open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Context) : + DocumentFilePigeonProxyApiRegistrar(binaryMessenger) { + + // Added to be overriden for tests. The test implementation calls `callback` immediately, instead + // of waiting for the main thread to run it. + internal open fun runOnMainThread(callback: Runnable) { + Handler(Looper.getMainLooper()).post { callback.run() } + } + + // Interface for an injectable SDK version checker. + @ChecksSdkIntAtLeast(parameter = 0) + open fun sdkIsAtLeast(version: Int): Boolean { + return Build.VERSION.SDK_INT >= version + } + + override fun getPigeonApiDocumentFile(): PigeonApiDocumentFile { + return DocumentFileProxyApi(this) + } + + override fun getPigeonApiContentResolver(): PigeonApiContentResolver { + return ContentResolverProxyApi(this) + } + + override fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse { + return InputStreamReadBytesResponseProxyApi(this) + } + + override fun getPigeonApiInputStream(): PigeonApiInputStream { + return InputStreamProxyApi(this) + } +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt new file mode 100644 index 000000000000..dde9ced5b5b6 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import android.content.ContentResolver +import androidx.core.net.toUri +import dev.flutter.packages.cross_file_android.ProxyApiRegistrar +import java.io.InputStream + +/** + * ProxyApi implementation for [ContentResolver]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class ContentResolverProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiContentResolver(pigeonRegistrar) { + override fun instance(): ContentResolver { + return pigeonRegistrar.context.contentResolver + } + + override fun openInputStream(pigeon_instance: ContentResolver,uri: String): InputStream? { + return pigeon_instance.openInputStream(uri.toUri()) + } +} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt index d43b6d84f12b..9df80f5cdf4b 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.0.5), do not edit directly. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -670,12 +670,140 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import androidx.documentfile.provider.DocumentFile + +/** + * ProxyApi implementation for [DocumentFile]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiDocumentFile(pigeonRegistrar) { + + override fun fromSingleUri(path: String): DocumentFile { + return DocumentFile(path) + } + + override fun canRead(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.canRead() + } + + override fun delete(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.delete() + } + + override fun exists(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.exists() + } + + override fun lastModified(pigeon_instance: DocumentFile): Long { + return pigeon_instance.lastModified() + } + + override fun length(pigeon_instance: DocumentFile): Long { + return pigeon_instance.length() + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import androidx.documentfile.provider.DocumentFile +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class DocumentFileTest { + @Test + fun fromSingleUri() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + assertTrue(api.fromSingleUri("myString") is DocumentFileProxyApi.DocumentFile) + } + + @Test + fun canRead() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.canRead()).thenReturn(value) + + assertEquals(value, api.canRead(instance )) + } + + @Test + fun delete() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.delete()).thenReturn(value) + + assertEquals(value, api.delete(instance )) + } + + @Test + fun exists() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.exists()).thenReturn(value) + + assertEquals(value, api.exists(instance )) + } + + @Test + fun lastModified() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = 0 + whenever(instance.lastModified()).thenReturn(value) + + assertEquals(value, api.lastModified(instance )) + } + + @Test + fun length() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = 0 + whenever(instance.length()).thenReturn(value) + + assertEquals(value, api.length(instance )) + } + +} +*/ /** https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { abstract fun instance(): android.content.ContentResolver - abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream + abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? companion object { @Suppress("LocalVariableName") @@ -751,6 +879,70 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePi } } + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import android.content.ContentResolver +import java.io.InputStream + +/** + * ProxyApi implementation for [ContentResolver]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class ContentResolverProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiContentResolver(pigeonRegistrar) { + + override fun instance(): android.content.ContentResolver { + return ContentResolver.instance + } + + override fun openInputStream(pigeon_instance: ContentResolver,uri: String): java.io.InputStream? { + return pigeon_instance.openInputStream(uri) + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import android.content.ContentResolver +import java.io.InputStream +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class ContentResolverTest { + @Test + fun openInputStream() { + val api = TestProxyApiRegistrar().getPigeonApiContentResolver() + + val instance = mock() + val uri = "myString" + val value = mock() + whenever(instance.openInputStream(uri)).thenReturn(value) + + assertEquals(value, api.openInputStream(instance, uri)) + } + +} +*/ @Suppress("UNCHECKED_CAST") abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long @@ -790,12 +982,86 @@ abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: D } } + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + +/** + * ProxyApi implementation for [InputStreamReadBytesResponse]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStreamReadBytesResponse(pigeonRegistrar) { + + override fun returnValue(pigeon_instance: InputStreamReadBytesResponse): Long { + return pigeon_instance.returnValue + } + + override fun bytes(pigeon_instance: InputStreamReadBytesResponse): ByteArray { + return pigeon_instance.bytes + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class InputStreamReadBytesResponseTest { + @Test + fun returnValue() { + val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() + + val instance = mock() + val value = 0 + whenever(instance.returnValue).thenReturn(value) + + assertEquals(value, api.returnValue(instance)) + } + + @Test + fun bytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() + + val instance = mock() + val value = byteArrayOf(0xA1.toByte()) + whenever(instance.bytes).thenReturn(value) + + assertEquals(value, api.bytes(instance)) + } + +} +*/ @Suppress("UNCHECKED_CAST") abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray + abstract fun skip(pigeon_instance: java.io.InputStream, n: Long): Long + companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { @@ -835,6 +1101,24 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as java.io.InputStream + val nArg = args[1] as Long + val wrapped: List = try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } @@ -869,3 +1153,94 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon } } + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import java.io.InputStream +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + +/** + * ProxyApi implementation for [InputStream]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStream(pigeonRegistrar) { + + override fun readBytes(pigeon_instance: InputStream,len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse { + return pigeon_instance.readBytes(len) + } + + override fun readAllBytes(pigeon_instance: InputStream): ByteArray { + return pigeon_instance.readAllBytes() + } + + override fun skip(pigeon_instance: InputStream,n: Long): Long { + return pigeon_instance.skip(n) + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import java.io.InputStream +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class InputStreamTest { + @Test + fun readBytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val len = 0 + val value = mock() + whenever(instance.readBytes(len)).thenReturn(value) + + assertEquals(value, api.readBytes(instance, len)) + } + + @Test + fun readAllBytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val value = byteArrayOf(0xA1.toByte()) + whenever(instance.readAllBytes()).thenReturn(value) + + assertEquals(value, api.readAllBytes(instance )) + } + + @Test + fun skip() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val n = 0 + val value = 0 + whenever(instance.skip(n)).thenReturn(value) + + assertEquals(value, api.skip(instance, n)) + } + +} +*/ diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt new file mode 100644 index 000000000000..151d96d14d13 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import androidx.core.net.toUri +import androidx.documentfile.provider.DocumentFile +import dev.flutter.packages.cross_file_android.ProxyApiRegistrar + +/** + * ProxyApi implementation for [DocumentFile]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiDocumentFile(pigeonRegistrar) { + override fun fromSingleUri(path: String): DocumentFile { + // Only returns null on platforms below Android 19. + return DocumentFile.fromSingleUri(pigeonRegistrar.context, path.toUri())!! + } + + override fun canRead(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.canRead() + } + + override fun delete(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.delete() + } + + override fun exists(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.exists() + } + + override fun lastModified(pigeon_instance: DocumentFile): Long { + return pigeon_instance.lastModified() + } + + override fun length(pigeon_instance: DocumentFile): Long { + return pigeon_instance.length() + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt new file mode 100644 index 000000000000..8dea856bd5d6 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -0,0 +1,31 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import java.io.InputStream +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import dev.flutter.packages.cross_file_android.ProxyApiRegistrar + +/** + * ProxyApi implementation for [InputStream]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStream(pigeonRegistrar) { + override fun readBytes(pigeon_instance: InputStream,len: Long): InputStreamReadBytesResponse { + val bytes = ByteArray(len.toInt()) + return InputStreamReadBytesResponse(pigeon_instance.read(bytes), bytes) + } + + override fun readAllBytes(pigeon_instance: InputStream): ByteArray { + return pigeon_instance.readBytes() + } + + override fun skip(pigeon_instance: InputStream, n: Long): Long { + return pigeon_instance.skip(n) + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt new file mode 100644 index 000000000000..f0fc309c84e9 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import dev.flutter.packages.cross_file_android.ProxyApiRegistrar + +/** + * ProxyApi implementation for [InputStreamReadBytesResponse]. + * + * This class may handle instantiating native object instances that are attached to a Dart + * instance or handle method calls on the associated native class or an instance of that class. + */ +class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStreamReadBytesResponse(pigeonRegistrar) { + + override fun returnValue(pigeon_instance: InputStreamReadBytesResponse): Long { + return pigeon_instance.returnValue.toLong() + } + + override fun bytes(pigeon_instance: InputStreamReadBytesResponse): ByteArray { + return pigeon_instance.bytes + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt new file mode 100644 index 000000000000..c9425f3ae6c4 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import android.content.ContentResolver +import java.io.InputStream +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class ContentResolverTest { + @Test + fun openInputStream() { + val api = TestProxyApiRegistrar().getPigeonApiContentResolver() + + val instance = mock() + val uri = "myString" + val value = mock() + whenever(instance.openInputStream(uri)).thenReturn(value) + + assertEquals(value, api.openInputStream(instance, uri)) + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt new file mode 100644 index 000000000000..faba0ca1709f --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -0,0 +1,81 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import androidx.documentfile.provider.DocumentFile +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class DocumentFileTest { + @Test + fun fromSingleUri() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + assertTrue(api.fromSingleUri("myString") is DocumentFileProxyApi.DocumentFile) + } + + @Test + fun canRead() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.canRead()).thenReturn(value) + + assertEquals(value, api.canRead(instance )) + } + + @Test + fun delete() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.delete()).thenReturn(value) + + assertEquals(value, api.delete(instance )) + } + + @Test + fun exists() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.exists()).thenReturn(value) + + assertEquals(value, api.exists(instance )) + } + + @Test + fun lastModified() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = 0 + whenever(instance.lastModified()).thenReturn(value) + + assertEquals(value, api.lastModified(instance )) + } + + @Test + fun length() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = 0 + whenever(instance.length()).thenReturn(value) + + assertEquals(value, api.length(instance )) + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt new file mode 100644 index 000000000000..2816e1a60605 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt @@ -0,0 +1,41 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class InputStreamReadBytesResponseTest { + @Test + fun returnValue() { + val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() + + val instance = mock() + val value = 0 + whenever(instance.returnValue).thenReturn(value) + + assertEquals(value, api.returnValue(instance)) + } + + @Test + fun bytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() + + val instance = mock() + val value = byteArrayOf(0xA1.toByte()) + whenever(instance.bytes).thenReturn(value) + + assertEquals(value, api.bytes(instance)) + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt new file mode 100644 index 000000000000..5de61ff58581 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -0,0 +1,43 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import java.io.InputStream +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.Mockito +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +class InputStreamTest { + @Test + fun readBytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val len = 0 + val value = mock() + whenever(instance.readBytes(len)).thenReturn(value) + + assertEquals(value, api.readBytes(instance, len)) + } + + @Test + fun readAllBytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val value = byteArrayOf(0xA1.toByte()) + whenever(instance.readAllBytes()).thenReturn(value) + + assertEquals(value, api.readAllBytes(instance )) + } + +} diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 1f1c2863db04..976818e5ef1d 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -1,8 +1,4 @@ import 'package:flutter/material.dart'; -import 'dart:async'; - -import 'package:flutter/services.dart'; -import 'package:cross_file_android/cross_file_android.dart'; void main() { runApp(const MyApp()); @@ -17,34 +13,10 @@ class MyApp extends StatefulWidget { class _MyAppState extends State { String _platformVersion = 'Unknown'; - final _crossFileAndroidPlugin = CrossFileAndroid(); @override void initState() { super.initState(); - initPlatformState(); - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - String platformVersion; - // Platform messages may fail, so we use a try/catch PlatformException. - // We also handle the message potentially returning null. - try { - platformVersion = - await _crossFileAndroidPlugin.getPlatformVersion() ?? 'Unknown platform version'; - } on PlatformException { - platformVersion = 'Failed to get platform version.'; - } - - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; - - setState(() { - _platformVersion = platformVersion; - }); } @override diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 25b266cef32d..6ec10bd82aeb 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -1,51 +1,2 @@ -import 'dart:convert'; - -import 'dart:typed_data'; - -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; - -base class AndroidXFile extends PlatformXFile { - AndroidXFile(super.path) : super.implementation(); - - @override - Future lastModified() { - // TODO: implement lastModified - throw UnimplementedError(); - } - - @override - Future length() { - // TODO: implement length - throw UnimplementedError(); - } - - @override - Stream openRead([int? start, int? end]) { - // TODO: implement openRead - throw UnimplementedError(); - } - - @override - Future readAsBytes() { - // TODO: implement readAsBytes - throw UnimplementedError(); - } - - @override - Future readAsString({Encoding encoding = utf8}) { - // TODO: implement readAsString - throw UnimplementedError(); - } - - @override - Future canRead() { - // TODO: implement canRead - throw UnimplementedError(); - } - - @override - Future exists() { - // TODO: implement exists - throw UnimplementedError(); - } -} +export 'src/android_cross_file.dart'; +export 'src/cross_file_android.dart'; diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index 0b43081d73ad..ce97aad7ea93 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -25,28 +25,36 @@ base class AndroidXFile extends PlatformXFile { @override Stream openRead([int? start, int? end]) async* { - final InputStream inputStream = await _contentResolver.openInputStream( + final InputStream? inputStream = await _contentResolver.openInputStream( params.path, ); - InputStreamReadBytesResponse response = await inputStream.readBytes(1024); - while(response.returnValue != -1) { - yield response.bytes; - response = await inputStream.readBytes(1024); + // TODO: add support for start and end. + if (inputStream case InputStream inputStream) { + InputStreamReadBytesResponse response = await inputStream.readBytes(1024); + while (response.returnValue != -1) { + yield response.bytes; + response = await inputStream.readBytes(1024); + } } + + throw _createNullInputStreamError(); } @override Future readAsBytes() async { - final InputStream inputStream = await _contentResolver.openInputStream( + final InputStream? inputStream = await _contentResolver.openInputStream( params.path, ); - return inputStream.readAllBytes(); + if (inputStream case InputStream inputStream) { + return inputStream.readAllBytes(); + } + + throw _createNullInputStreamError(); } @override Future readAsString({Encoding encoding = utf8}) { - // TODO: implement readAsString - throw UnimplementedError(); + return utf8.decodeStream(openRead()); } @override @@ -54,4 +62,11 @@ base class AndroidXFile extends PlatformXFile { @override Future exists() => _documentFile.exists(); + + UnsupportedError _createNullInputStreamError() { + return UnsupportedError( + 'Failed to get native InputStream from file with path: ${params.path}. ' + 'App may not have permissions to access file.', + ); + } } diff --git a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart index 5e7cf559a9e6..962b53a3c47f 100644 --- a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.0.5), do not edit directly. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -844,7 +844,7 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { return pigeonVar_instance; } - Future openInputStream(String uri) async { + Future openInputStream(String uri) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecContentResolver; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -868,13 +868,8 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { message: pigeonVar_replyList[1] as String?, details: pigeonVar_replyList[2], ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); } else { - return (pigeonVar_replyList[0] as InputStream?)!; + return (pigeonVar_replyList[0] as InputStream?); } } @@ -1106,6 +1101,40 @@ class InputStream extends PigeonInternalProxyApiBaseClass { } } + Future skip(int n) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecInputStream; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.InputStream.skip'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, n]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as int?)!; + } + } + @override InputStream pigeon_copy() { return InputStream.pigeon_detached( diff --git a/packages/cross_file/cross_file_android/pigeons/document_file.dart b/packages/cross_file/cross_file_android/pigeons/document_file.dart index aef07ae0921f..b24db90ad70f 100644 --- a/packages/cross_file/cross_file_android/pigeons/document_file.dart +++ b/packages/cross_file/cross_file_android/pigeons/document_file.dart @@ -40,7 +40,7 @@ abstract class ContentResolver { @static late final ContentResolver instance; - InputStream openInputStream(String uri); + InputStream? openInputStream(String uri); } @ProxyApi( @@ -62,4 +62,6 @@ abstract class InputStream { InputStreamReadBytesResponse readBytes(int len); Uint8List readAllBytes(); + + int skip(int n); } diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index bb734c544826..a93133ada491 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -16,7 +16,7 @@ flutter: android: package: dev.flutter.packages.cross_file_android pluginClass: CrossFileAndroidPlugin - dartPluginClass: XFileAndroid + dartPluginClass: CrossFileAndroid dependencies: flutter: @@ -27,7 +27,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - pigeon: ^26.0.5 + pigeon: ^26.1.0 topics: - file From 10400cf858325b06eac863e55d359d8101651880 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 14 Nov 2025 18:50:02 -0500 Subject: [PATCH 013/398] example use for android working --- .../lib/cross_file_android.dart | 2 + .../lib/src/android_cross_file.dart | 4 +- .../FileSelectorApiImpl.java | 36 ++++ .../GeneratedFileSelectorApi.java | 151 ++++++++-------- .../example/lib/open_text_page.dart | 11 +- .../example/pubspec.yaml | 2 + .../lib/src/file_selector_android.dart | 18 ++ .../lib/src/file_selector_api.g.dart | 162 +++++++++--------- .../pigeons/file_selector_api.dart | 3 + .../file_selector_android/pubspec.yaml | 2 + 10 files changed, 228 insertions(+), 163 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 6ec10bd82aeb..6d9b4deabbbb 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -1,2 +1,4 @@ export 'src/android_cross_file.dart'; export 'src/cross_file_android.dart'; +export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' + show PlatformXFileCreationParams; diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index ce97aad7ea93..501a9fe7dad7 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -35,9 +35,9 @@ base class AndroidXFile extends PlatformXFile { yield response.bytes; response = await inputStream.readBytes(1024); } + } else { + throw _createNullInputStreamError(); } - - throw _createNullInputStreamError(); } @override diff --git a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java index 2504c9e00b8d..aa1941b6e0a8 100644 --- a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java +++ b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java @@ -131,6 +131,42 @@ public void onResult(int resultCode, @Nullable Intent data) { } } + @Override + public void openFile2(@Nullable String initialDirectory, @NonNull GeneratedFileSelectorApi.FileTypes allowedTypes, @NonNull GeneratedFileSelectorApi.NullableResult result) { + final Intent intent = objectFactory.newIntent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + + setMimeTypes(intent, allowedTypes); + trySetInitialDirectory(intent, initialDirectory); + + try { + startActivityForResult( + intent, + OPEN_FILE, + new OnResultListener() { + @Override + public void onResult(int resultCode, @Nullable Intent data) { + if (resultCode == Activity.RESULT_OK && data != null) { + final Uri uri = data.getData(); + if (uri == null) { + // No data retrieved from opening file. + result.error(new Exception("Failed to retrieve data from opening file.")); + return; + } + + result.success(uri.toString()); + Log.d(TAG, "File path: " + uri); + } else { + result.success(null); + } + } + }); + } catch (Exception exception) { + result.error(exception); + } + } + + @Override public void openFiles( @Nullable String initialDirectory, diff --git a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java index 3fde65bea5a6..60c1094a6cdd 100644 --- a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java +++ b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. // See also: https://pub.dev/packages/pigeon package dev.flutter.packages.file_selector_android; @@ -22,7 +22,10 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; /** Generated class from Pigeon. */ @@ -38,7 +41,8 @@ public static class FlutterError extends RuntimeException { /** The error details. Must be a datatype supported by the api codec. */ public final Object details; - public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) { + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) + { super(message); this.code = code; this.details = details; @@ -57,7 +61,7 @@ protected static ArrayList wrapError(@NonNull Throwable exception) { errorList.add(exception.toString()); errorList.add(exception.getClass().getSimpleName()); errorList.add( - "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); } return errorList; } @@ -112,15 +116,10 @@ public void setMessage(@NonNull String setterArg) { @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } FileSelectorNativeException that = (FileSelectorNativeException) o; - return fileSelectorExceptionCode.equals(that.fileSelectorExceptionCode) - && message.equals(that.message); + return fileSelectorExceptionCode.equals(that.fileSelectorExceptionCode) && message.equals(that.message); } @Override @@ -133,8 +132,7 @@ public static final class Builder { private @Nullable FileSelectorExceptionCode fileSelectorExceptionCode; @CanIgnoreReturnValue - public @NonNull Builder setFileSelectorExceptionCode( - @NonNull FileSelectorExceptionCode setterArg) { + public @NonNull Builder setFileSelectorExceptionCode(@NonNull FileSelectorExceptionCode setterArg) { this.fileSelectorExceptionCode = setterArg; return this; } @@ -163,12 +161,10 @@ ArrayList toList() { return toListResult; } - static @NonNull FileSelectorNativeException fromList( - @NonNull ArrayList pigeonVar_list) { + static @NonNull FileSelectorNativeException fromList(@NonNull ArrayList pigeonVar_list) { FileSelectorNativeException pigeonResult = new FileSelectorNativeException(); Object fileSelectorExceptionCode = pigeonVar_list.get(0); - pigeonResult.setFileSelectorExceptionCode( - (FileSelectorExceptionCode) fileSelectorExceptionCode); + pigeonResult.setFileSelectorExceptionCode((FileSelectorExceptionCode) fileSelectorExceptionCode); Object message = pigeonVar_list.get(1); pigeonResult.setMessage((String) message); return pigeonResult; @@ -251,19 +247,10 @@ public void setFileSelectorNativeException(@Nullable FileSelectorNativeException @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } FileResponse that = (FileResponse) o; - return path.equals(that.path) - && Objects.equals(mimeType, that.mimeType) - && Objects.equals(name, that.name) - && size.equals(that.size) - && Arrays.equals(bytes, that.bytes) - && Objects.equals(fileSelectorNativeException, that.fileSelectorNativeException); + return path.equals(that.path) && Objects.equals(mimeType, that.mimeType) && Objects.equals(name, that.name) && size.equals(that.size) && Arrays.equals(bytes, that.bytes) && Objects.equals(fileSelectorNativeException, that.fileSelectorNativeException); } @Override @@ -318,8 +305,7 @@ public static final class Builder { private @Nullable FileSelectorNativeException fileSelectorNativeException; @CanIgnoreReturnValue - public @NonNull Builder setFileSelectorNativeException( - @Nullable FileSelectorNativeException setterArg) { + public @NonNull Builder setFileSelectorNativeException(@Nullable FileSelectorNativeException setterArg) { this.fileSelectorNativeException = setterArg; return this; } @@ -361,8 +347,7 @@ ArrayList toList() { Object bytes = pigeonVar_list.get(4); pigeonResult.setBytes((byte[]) bytes); Object fileSelectorNativeException = pigeonVar_list.get(5); - pigeonResult.setFileSelectorNativeException( - (FileSelectorNativeException) fileSelectorNativeException); + pigeonResult.setFileSelectorNativeException((FileSelectorNativeException) fileSelectorNativeException); return pigeonResult; } } @@ -400,12 +385,8 @@ public void setExtensions(@NonNull List setterArg) { @Override public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } + if (this == o) { return true; } + if (o == null || getClass() != o.getClass()) { return false; } FileTypes that = (FileTypes) o; return mimeTypes.equals(that.mimeTypes) && extensions.equals(that.extensions); } @@ -467,13 +448,10 @@ private PigeonCodec() {} @Override protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { switch (type) { - case (byte) 129: - { - Object value = readValue(buffer); - return value == null - ? null - : FileSelectorExceptionCode.values()[((Long) value).intValue()]; - } + case (byte) 129: { + Object value = readValue(buffer); + return value == null ? null : FileSelectorExceptionCode.values()[((Long) value).intValue()]; + } case (byte) 130: return FileSelectorNativeException.fromList((ArrayList) readValue(buffer)); case (byte) 131: @@ -505,6 +483,7 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { } } + /** Asynchronous error handling return type for non-nullable API method returns. */ public interface Result { /** Success case callback method for handling returns. */ @@ -532,57 +511,43 @@ public interface VoidResult { /** * An API to call to native code to select files or directories. * - *

Generated interface from Pigeon that represents a handler of messages from Flutter. + * Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FileSelectorApi { /** * Opens a file dialog for loading files and returns a file path. * - *

Returns `null` if user cancels the operation. + * Returns `null` if user cancels the operation. */ - void openFile( - @Nullable String initialDirectory, - @NonNull FileTypes allowedTypes, - @NonNull NullableResult result); + void openFile(@Nullable String initialDirectory, @NonNull FileTypes allowedTypes, @NonNull NullableResult result); + + void openFile2(@Nullable String initialDirectory, @NonNull FileTypes allowedTypes, @NonNull NullableResult result); /** - * Opens a file dialog for loading files and returns a list of file responses chosen by the - * user. + * Opens a file dialog for loading files and returns a list of file responses + * chosen by the user. */ - void openFiles( - @Nullable String initialDirectory, - @NonNull FileTypes allowedTypes, - @NonNull Result> result); + void openFiles(@Nullable String initialDirectory, @NonNull FileTypes allowedTypes, @NonNull Result> result); /** * Opens a file dialog for loading directories and returns a directory path. * - *

Returns `null` if user cancels the operation. + * Returns `null` if user cancels the operation. */ - void getDirectoryPath( - @Nullable String initialDirectory, @NonNull NullableResult result); + void getDirectoryPath(@Nullable String initialDirectory, @NonNull NullableResult result); /** The codec used by FileSelectorApi. */ static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } - /** - * Sets up an instance of `FileSelectorApi` to handle messages through the `binaryMessenger`. - */ + /**Sets up an instance of `FileSelectorApi` to handle messages through the `binaryMessenger`. */ static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable FileSelectorApi api) { setUp(binaryMessenger, "", api); } - - static void setUp( - @NonNull BinaryMessenger binaryMessenger, - @NonNull String messageChannelSuffix, - @Nullable FileSelectorApi api) { + static void setUp(@NonNull BinaryMessenger binaryMessenger, @NonNull String messageChannelSuffix, @Nullable FileSelectorApi api) { messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; { BasicMessageChannel channel = new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile" - + messageChannelSuffix, - getCodec()); + binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile" + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { @@ -612,10 +577,37 @@ public void error(Throwable error) { { BasicMessageChannel channel = new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles" - + messageChannelSuffix, - getCodec()); + binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile2" + messageChannelSuffix, getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + ArrayList wrapped = new ArrayList<>(); + ArrayList args = (ArrayList) message; + String initialDirectoryArg = (String) args.get(0); + FileTypes allowedTypesArg = (FileTypes) args.get(1); + NullableResult resultCallback = + new NullableResult() { + public void success(String result) { + wrapped.add(0, result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + ArrayList wrappedError = wrapError(error); + reply.reply(wrappedError); + } + }; + + api.openFile2(initialDirectoryArg, allowedTypesArg, resultCallback); + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles" + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { @@ -645,10 +637,7 @@ public void error(Throwable error) { { BasicMessageChannel channel = new BasicMessageChannel<>( - binaryMessenger, - "dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath" - + messageChannelSuffix, - getCodec()); + binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath" + messageChannelSuffix, getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { diff --git a/packages/file_selector/file_selector_android/example/lib/open_text_page.dart b/packages/file_selector/file_selector_android/example/lib/open_text_page.dart index 8c22c88ca3b6..478c4a27f6c5 100644 --- a/packages/file_selector/file_selector_android/example/lib/open_text_page.dart +++ b/packages/file_selector/file_selector_android/example/lib/open_text_page.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cross_file_android/cross_file_android.dart'; +import 'package:file_selector_android/file_selector_android.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:flutter/material.dart'; @@ -17,15 +19,20 @@ class OpenTextPage extends StatelessWidget { extensions: ['txt', 'json'], uniformTypeIdentifiers: ['public.text'], ); - final XFile? file = await FileSelectorPlatform.instance.openFile( + final AndroidXFile? file = await FileSelectorAndroid().openFile2( acceptedTypeGroups: [typeGroup], ); if (file == null) { // Operation was canceled by the user. return; } - final String fileName = file.name; + final String fileName = 'Some Name'; final String fileContent = await file.readAsString(); + print(await file.exists()); + print(await file.canRead()); + print(await file.length()); + print(await file.lastModified()); + print(await file.readAsBytes()); if (context.mounted) { await showDialog( diff --git a/packages/file_selector/file_selector_android/example/pubspec.yaml b/packages/file_selector/file_selector_android/example/pubspec.yaml index 52f274b2edf1..0f2483493f9c 100644 --- a/packages/file_selector/file_selector_android/example/pubspec.yaml +++ b/packages/file_selector/file_selector_android/example/pubspec.yaml @@ -7,6 +7,8 @@ environment: flutter: ">=3.32.0" dependencies: + cross_file_android: + path: ../../../cross_file/cross_file_android file_selector_android: # When depending on this package from a real application you should use: # file_selector_android: ^x.y.z diff --git a/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart b/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart index 303330d3de3f..1e6821b5b437 100644 --- a/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart +++ b/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart @@ -4,6 +4,7 @@ // ignore_for_file: public_member_api_docs +import 'package:cross_file_android/cross_file_android.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:flutter/cupertino.dart'; @@ -35,6 +36,23 @@ class FileSelectorAndroid extends FileSelectorPlatform { return file == null ? null : _xFileFromFileResponse(file); } + Future openFile2({ + List? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) async { + final String? path = await _api.openFile2( + initialDirectory, + _fileTypesFromTypeGroups(acceptedTypeGroups), + ); + + if (path case final String path) { + return AndroidXFile(PlatformXFileCreationParams(path: path)); + } + + return null; + } + @override Future> openFiles({ List? acceptedTypeGroups, diff --git a/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart b/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart index 4c8640886c50..deaa438542c0 100644 --- a/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart +++ b/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.0.1), do not edit directly. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -17,25 +17,21 @@ PlatformException _createConnectionError(String channelName) { message: 'Unable to establish connection on channel: "$channelName".', ); } - bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed.every( - ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), - ); + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every( - (MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key]), - ); + return a.length == b.length && a.entries.every((MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key])); } return a == b; } + enum FileSelectorExceptionCode { securityException, ioException, @@ -54,12 +50,14 @@ class FileSelectorNativeException { String message; List _toList() { - return [fileSelectorExceptionCode, message]; + return [ + fileSelectorExceptionCode, + message, + ]; } Object encode() { - return _toList(); - } + return _toList(); } static FileSelectorNativeException decode(Object result) { result as List; @@ -72,8 +70,7 @@ class FileSelectorNativeException { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! FileSelectorNativeException || - other.runtimeType != runtimeType) { + if (other is! FileSelectorNativeException || other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { @@ -84,7 +81,8 @@ class FileSelectorNativeException { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => Object.hashAll(_toList()) +; } class FileResponse { @@ -121,8 +119,7 @@ class FileResponse { } Object encode() { - return _toList(); - } + return _toList(); } static FileResponse decode(Object result) { result as List; @@ -150,23 +147,29 @@ class FileResponse { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => Object.hashAll(_toList()) +; } class FileTypes { - FileTypes({required this.mimeTypes, required this.extensions}); + FileTypes({ + required this.mimeTypes, + required this.extensions, + }); List mimeTypes; List extensions; List _toList() { - return [mimeTypes, extensions]; + return [ + mimeTypes, + extensions, + ]; } Object encode() { - return _toList(); - } + return _toList(); } static FileTypes decode(Object result) { result as List; @@ -190,9 +193,11 @@ class FileTypes { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => Object.hashAll(_toList()) +; } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -200,16 +205,16 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileSelectorExceptionCode) { + } else if (value is FileSelectorExceptionCode) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is FileSelectorNativeException) { + } else if (value is FileSelectorNativeException) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is FileResponse) { + } else if (value is FileResponse) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is FileTypes) { + } else if (value is FileTypes) { buffer.putUint8(132); writeValue(buffer, value.encode()); } else { @@ -220,14 +225,14 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: final int? value = readValue(buffer) as int?; return value == null ? null : FileSelectorExceptionCode.values[value]; - case 130: + case 130: return FileSelectorNativeException.decode(readValue(buffer)!); - case 131: + case 131: return FileResponse.decode(readValue(buffer)!); - case 132: + case 132: return FileTypes.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -240,13 +245,9 @@ class FileSelectorApi { /// Constructor for [FileSelectorApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - FileSelectorApi({ - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty - ? '.$messageChannelSuffix' - : ''; + FileSelectorApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -256,21 +257,14 @@ class FileSelectorApi { /// Opens a file dialog for loading files and returns a file path. /// /// Returns `null` if user cancels the operation. - Future openFile( - String? initialDirectory, - FileTypes allowedTypes, - ) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [initialDirectory, allowedTypes], + Future openFile(String? initialDirectory, FileTypes allowedTypes) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory, allowedTypes]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -286,23 +280,39 @@ class FileSelectorApi { } } + Future openFile2(String? initialDirectory, FileTypes allowedTypes) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile2$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory, allowedTypes]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as String?); + } + } + /// Opens a file dialog for loading files and returns a list of file responses /// chosen by the user. - Future> openFiles( - String? initialDirectory, - FileTypes allowedTypes, - ) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [initialDirectory, allowedTypes], + Future> openFiles(String? initialDirectory, FileTypes allowedTypes) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory, allowedTypes]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -327,17 +337,13 @@ class FileSelectorApi { /// /// Returns `null` if user cancels the operation. Future getDirectoryPath(String? initialDirectory) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [initialDirectory], + final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { diff --git a/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart b/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart index 1aa94ae1bc9a..dba4dd278f64 100644 --- a/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart +++ b/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart @@ -51,6 +51,9 @@ abstract class FileSelectorApi { @async FileResponse? openFile(String? initialDirectory, FileTypes allowedTypes); + @async + String? openFile2(String? initialDirectory, FileTypes allowedTypes); + /// Opens a file dialog for loading files and returns a list of file responses /// chosen by the user. @async diff --git a/packages/file_selector/file_selector_android/pubspec.yaml b/packages/file_selector/file_selector_android/pubspec.yaml index 8a1a11f79805..84e73fd1d3f8 100644 --- a/packages/file_selector/file_selector_android/pubspec.yaml +++ b/packages/file_selector/file_selector_android/pubspec.yaml @@ -18,6 +18,8 @@ flutter: pluginClass: FileSelectorAndroidPlugin dependencies: + cross_file_android: + path: ../../cross_file/cross_file_android file_selector_platform_interface: ^2.5.0 flutter: sdk: flutter From 7ad47ffae1e8f14e9b78012213e66bd765b08b77 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 15 Nov 2025 09:57:04 -0600 Subject: [PATCH 014/398] base ios flutter create --- packages/cross_file/cross_file_ios/.gitignore | 33 + packages/cross_file/cross_file_ios/.metadata | 30 + .../cross_file/cross_file_ios/CHANGELOG.md | 3 + packages/cross_file/cross_file_ios/LICENSE | 1 + packages/cross_file/cross_file_ios/README.md | 15 + .../cross_file_ios/analysis_options.yaml | 4 + .../cross_file_ios/example/.gitignore | 45 ++ .../cross_file_ios/example/README.md | 16 + .../example/analysis_options.yaml | 28 + .../plugin_integration_test.dart | 25 + .../cross_file_ios/example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 26 + .../example/ios/Flutter/Debug.xcconfig | 1 + .../example/ios/Flutter/Release.xcconfig | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 619 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 101 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 ++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example/ios/Runner/Info.plist | 49 ++ .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/ios/RunnerTests/RunnerTests.swift | 27 + .../cross_file_ios/example/lib/main.dart | 63 ++ .../cross_file_ios/example/pubspec.yaml | 85 +++ .../example/test/widget_test.dart | 27 + .../cross_file/cross_file_ios/ios/.gitignore | 38 ++ .../cross_file_ios/ios/Assets/.gitkeep | 0 .../ios/Classes/CrossFileIosPlugin.swift | 19 + .../ios/Resources/PrivacyInfo.xcprivacy | 14 + .../cross_file_ios/ios/cross_file_ios.podspec | 29 + .../cross_file_ios/lib/cross_file_ios.dart | 8 + .../lib/cross_file_ios_method_channel.dart | 17 + .../cross_file_ios_platform_interface.dart | 29 + .../cross_file/cross_file_ios/pubspec.yaml | 69 ++ .../cross_file_ios_method_channel_test.dart | 27 + .../test/cross_file_ios_test.dart | 29 + 63 files changed, 1785 insertions(+) create mode 100644 packages/cross_file/cross_file_ios/.gitignore create mode 100644 packages/cross_file/cross_file_ios/.metadata create mode 100644 packages/cross_file/cross_file_ios/CHANGELOG.md create mode 100644 packages/cross_file/cross_file_ios/LICENSE create mode 100644 packages/cross_file/cross_file_ios/README.md create mode 100644 packages/cross_file/cross_file_ios/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_ios/example/.gitignore create mode 100644 packages/cross_file/cross_file_ios/example/README.md create mode 100644 packages/cross_file/cross_file_ios/example/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart create mode 100644 packages/cross_file/cross_file_ios/example/ios/.gitignore create mode 100644 packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist create mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/cross_file/cross_file_ios/example/lib/main.dart create mode 100644 packages/cross_file/cross_file_ios/example/pubspec.yaml create mode 100644 packages/cross_file/cross_file_ios/example/test/widget_test.dart create mode 100644 packages/cross_file/cross_file_ios/ios/.gitignore create mode 100644 packages/cross_file/cross_file_ios/ios/Assets/.gitkeep create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy create mode 100644 packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec create mode 100644 packages/cross_file/cross_file_ios/lib/cross_file_ios.dart create mode 100644 packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart create mode 100644 packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart create mode 100644 packages/cross_file/cross_file_ios/pubspec.yaml create mode 100644 packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart create mode 100644 packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart diff --git a/packages/cross_file/cross_file_ios/.gitignore b/packages/cross_file/cross_file_ios/.gitignore new file mode 100644 index 000000000000..b9d7f25b91b6 --- /dev/null +++ b/packages/cross_file/cross_file_ios/.gitignore @@ -0,0 +1,33 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/packages/cross_file/cross_file_ios/.metadata b/packages/cross_file/cross_file_ios/.metadata new file mode 100644 index 000000000000..d99a0a7fe63c --- /dev/null +++ b/packages/cross_file/cross_file_ios/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "81928eeb91fcdb2bc7a2dc35622627b31581549f" + channel: "main" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + - platform: ios + create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_ios/CHANGELOG.md b/packages/cross_file/cross_file_ios/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/cross_file/cross_file_ios/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_ios/LICENSE b/packages/cross_file/cross_file_ios/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/cross_file/cross_file_ios/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/cross_file/cross_file_ios/README.md b/packages/cross_file/cross_file_ios/README.md new file mode 100644 index 000000000000..43322a17da3e --- /dev/null +++ b/packages/cross_file/cross_file_ios/README.md @@ -0,0 +1,15 @@ +# cross_file_ios + +A new Flutter plugin project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/to/develop-plugins), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/packages/cross_file/cross_file_ios/analysis_options.yaml b/packages/cross_file/cross_file_ios/analysis_options.yaml new file mode 100644 index 000000000000..a5744c1cfbe7 --- /dev/null +++ b/packages/cross_file/cross_file_ios/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_ios/example/.gitignore b/packages/cross_file/cross_file_ios/example/.gitignore new file mode 100644 index 000000000000..3820a95c65c3 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/cross_file/cross_file_ios/example/README.md b/packages/cross_file/cross_file_ios/example/README.md new file mode 100644 index 000000000000..d1ba652b9015 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/README.md @@ -0,0 +1,16 @@ +# cross_file_ios_example + +Demonstrates how to use the cross_file_ios plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/cross_file/cross_file_ios/example/analysis_options.yaml b/packages/cross_file/cross_file_ios/example/analysis_options.yaml new file mode 100644 index 000000000000..0d2902135cae --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart new file mode 100644 index 000000000000..ad1fbfaa88ad --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart @@ -0,0 +1,25 @@ +// This is a basic Flutter integration test. +// +// Since integration tests run in a full Flutter application, they can interact +// with the host side of a plugin implementation, unlike Dart unit tests. +// +// For more information about Flutter integration tests, please see +// https://flutter.dev/to/integration-testing + + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:cross_file_ios/cross_file_ios.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getPlatformVersion test', (WidgetTester tester) async { + final CrossFileIos plugin = CrossFileIos(); + final String? version = await plugin.getPlatformVersion(); + // The version string depends on the host platform running the test, so + // just assert that some non-empty string is returned. + expect(version?.isNotEmpty, true); + }); +} diff --git a/packages/cross_file/cross_file_ios/example/ios/.gitignore b/packages/cross_file/cross_file_ios/example/ios/.gitignore new file mode 100644 index 000000000000..7a7f9873ad7d --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist b/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000000..1dc6cf7652ba --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 13.0 + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..592ceee85b89 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..592ceee85b89 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..334602436974 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,619 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..919434a6254f --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..e3773d42e24c --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift b/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000000..626664468b89 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..d36b1fab2d9d --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000000..0bedcf2fd467 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000000..89c2725b70f1 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000000..f2e259c7c939 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard b/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000000..f3c28516fb38 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist b/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist new file mode 100644 index 000000000000..df7346c71700 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Cross File Ios + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + cross_file_ios_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h b/packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000000..308a2a560b42 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..f530c51068f3 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,27 @@ +import Flutter +import UIKit +import XCTest + + +@testable import cross_file_ios + +// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. +// +// See https://developer.apple.com/documentation/xctest for more information about using XCTest. + +class RunnerTests: XCTestCase { + + func testGetPlatformVersion() { + let plugin = CrossFileIosPlugin() + + let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) + + let resultExpectation = expectation(description: "result block must be called.") + plugin.handle(call) { result in + XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) + resultExpectation.fulfill() + } + waitForExpectations(timeout: 1) + } + +} diff --git a/packages/cross_file/cross_file_ios/example/lib/main.dart b/packages/cross_file/cross_file_ios/example/lib/main.dart new file mode 100644 index 000000000000..80109a0a4cdf --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/lib/main.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:cross_file_ios/cross_file_ios.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + String _platformVersion = 'Unknown'; + final _crossFileIosPlugin = CrossFileIos(); + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initPlatformState() async { + String platformVersion; + // Platform messages may fail, so we use a try/catch PlatformException. + // We also handle the message potentially returning null. + try { + platformVersion = + await _crossFileIosPlugin.getPlatformVersion() ?? 'Unknown platform version'; + } on PlatformException { + platformVersion = 'Failed to get platform version.'; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) return; + + setState(() { + _platformVersion = platformVersion; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Plugin example app'), + ), + body: Center( + child: Text('Running on: $_platformVersion\n'), + ), + ), + ); + } +} diff --git a/packages/cross_file/cross_file_ios/example/pubspec.yaml b/packages/cross_file/cross_file_ios/example/pubspec.yaml new file mode 100644 index 000000000000..6d4b97118544 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/pubspec.yaml @@ -0,0 +1,85 @@ +name: cross_file_ios_example +description: "Demonstrates how to use the cross_file_ios plugin." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ^3.10.0-200.0.dev + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + cross_file_ios: + # When depending on this package from a real application you should use: + # cross_file_ios: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_ios/example/test/widget_test.dart b/packages/cross_file/cross_file_ios/example/test/widget_test.dart new file mode 100644 index 000000000000..0dfc28c4f8f3 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cross_file_ios_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => widget is Text && + widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/cross_file/cross_file_ios/ios/.gitignore b/packages/cross_file/cross_file_ios/ios/.gitignore new file mode 100644 index 000000000000..034771fc9c9b --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/.gitignore @@ -0,0 +1,38 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/ephemeral/ +/Flutter/flutter_export_environment.sh diff --git a/packages/cross_file/cross_file_ios/ios/Assets/.gitkeep b/packages/cross_file/cross_file_ios/ios/Assets/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift new file mode 100644 index 000000000000..a68b0e4ab79d --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift @@ -0,0 +1,19 @@ +import Flutter +import UIKit + +public class CrossFileIosPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "cross_file_ios", binaryMessenger: registrar.messenger()) + let instance = CrossFileIosPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getPlatformVersion": + result("iOS " + UIDevice.current.systemVersion) + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy b/packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 000000000000..a34b7e2e60cc --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec b/packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec new file mode 100644 index 000000000000..c009200d1815 --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec @@ -0,0 +1,29 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint cross_file_ios.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'cross_file_ios' + s.version = '0.0.1' + s.summary = 'A new Flutter plugin project.' + s.description = <<-DESC +A new Flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '13.0' + + # Flutter.framework does not contain a i386 slice. + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } + s.swift_version = '5.0' + + # If your plugin requires a privacy manifest, for example if it uses any + # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your + # plugin's privacy impact, and then uncomment this line. For more information, + # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files + # s.resource_bundles = {'cross_file_ios_privacy' => ['Resources/PrivacyInfo.xcprivacy']} +end diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart new file mode 100644 index 000000000000..405e5c816f59 --- /dev/null +++ b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart @@ -0,0 +1,8 @@ + +import 'cross_file_ios_platform_interface.dart'; + +class CrossFileIos { + Future getPlatformVersion() { + return CrossFileIosPlatform.instance.getPlatformVersion(); + } +} diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart new file mode 100644 index 000000000000..d9b2a95634ba --- /dev/null +++ b/packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart @@ -0,0 +1,17 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'cross_file_ios_platform_interface.dart'; + +/// An implementation of [CrossFileIosPlatform] that uses method channels. +class MethodChannelCrossFileIos extends CrossFileIosPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + final methodChannel = const MethodChannel('cross_file_ios'); + + @override + Future getPlatformVersion() async { + final version = await methodChannel.invokeMethod('getPlatformVersion'); + return version; + } +} diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart new file mode 100644 index 000000000000..b89b622ac789 --- /dev/null +++ b/packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart @@ -0,0 +1,29 @@ +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'cross_file_ios_method_channel.dart'; + +abstract class CrossFileIosPlatform extends PlatformInterface { + /// Constructs a CrossFileIosPlatform. + CrossFileIosPlatform() : super(token: _token); + + static final Object _token = Object(); + + static CrossFileIosPlatform _instance = MethodChannelCrossFileIos(); + + /// The default instance of [CrossFileIosPlatform] to use. + /// + /// Defaults to [MethodChannelCrossFileIos]. + static CrossFileIosPlatform get instance => _instance; + + /// Platform-specific implementations should set this with their own + /// platform-specific class that extends [CrossFileIosPlatform] when + /// they register themselves. + static set instance(CrossFileIosPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Future getPlatformVersion() { + throw UnimplementedError('platformVersion() has not been implemented.'); + } +} diff --git a/packages/cross_file/cross_file_ios/pubspec.yaml b/packages/cross_file/cross_file_ios/pubspec.yaml new file mode 100644 index 000000000000..b4e13960a004 --- /dev/null +++ b/packages/cross_file/cross_file_ios/pubspec.yaml @@ -0,0 +1,69 @@ +name: cross_file_ios +description: "A new Flutter plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.10.0-200.0.dev + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) + # which should be registered in the plugin registry. This is required for + # using method channels. + # The Android 'package' specifies package in which the registered class is. + # This is required for using method channels on Android. + # The 'ffiPlugin' specifies that native code should be built and bundled. + # This is required for using `dart:ffi`. + # All these are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + ios: + pluginClass: CrossFileIosPlugin + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart b/packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart new file mode 100644 index 000000000000..1a1a1df6a14d --- /dev/null +++ b/packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart @@ -0,0 +1,27 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_ios/cross_file_ios_method_channel.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + MethodChannelCrossFileIos platform = MethodChannelCrossFileIos(); + const MethodChannel channel = MethodChannel('cross_file_ios'); + + setUp(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( + channel, + (MethodCall methodCall) async { + return '42'; + }, + ); + }); + + tearDown(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null); + }); + + test('getPlatformVersion', () async { + expect(await platform.getPlatformVersion(), '42'); + }); +} diff --git a/packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart b/packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart new file mode 100644 index 000000000000..cff9c160310d --- /dev/null +++ b/packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart @@ -0,0 +1,29 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_ios/cross_file_ios.dart'; +import 'package:cross_file_ios/cross_file_ios_platform_interface.dart'; +import 'package:cross_file_ios/cross_file_ios_method_channel.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockCrossFileIosPlatform + with MockPlatformInterfaceMixin + implements CrossFileIosPlatform { + + @override + Future getPlatformVersion() => Future.value('42'); +} + +void main() { + final CrossFileIosPlatform initialPlatform = CrossFileIosPlatform.instance; + + test('$MethodChannelCrossFileIos is the default instance', () { + expect(initialPlatform, isInstanceOf()); + }); + + test('getPlatformVersion', () async { + CrossFileIos crossFileIosPlugin = CrossFileIos(); + MockCrossFileIosPlatform fakePlatform = MockCrossFileIosPlatform(); + CrossFileIosPlatform.instance = fakePlatform; + + expect(await crossFileIosPlugin.getPlatformVersion(), '42'); + }); +} From ff250a9c08e992365d6d105f4a1267835d85a5a7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 15 Nov 2025 11:10:33 -0600 Subject: [PATCH 015/398] start of ios and some android notes --- .../lib/src/android_cross_file.dart | 7 +- .../lib/src/cross_file_android.dart | 2 +- .../example/ios/Flutter/Debug.xcconfig | 1 + .../example/ios/Flutter/Release.xcconfig | 1 + .../cross_file_ios/example/ios/Podfile | 43 +++++++++++ ...sPlugin.swift => CrossFileIOSPlugin.swift} | 2 +- .../cross_file_ios/lib/cross_file_ios.dart | 12 +-- .../lib/cross_file_ios_method_channel.dart | 17 ----- .../cross_file_ios_platform_interface.dart | 29 -------- .../lib/src/cross_file_ios.dart | 15 ++++ .../lib/src/ios_cross_file.dart | 71 ++++++++++++++++++ .../cross_file/cross_file_ios/pubspec.yaml | 73 +++++-------------- 12 files changed, 159 insertions(+), 114 deletions(-) create mode 100644 packages/cross_file/cross_file_ios/example/ios/Podfile rename packages/cross_file/cross_file_ios/ios/Classes/{CrossFileIosPlugin.swift => CrossFileIOSPlugin.swift} (90%) delete mode 100644 packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart delete mode 100644 packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart create mode 100644 packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart create mode 100644 packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index 501a9fe7dad7..7492939adb5d 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -33,7 +33,7 @@ base class AndroidXFile extends PlatformXFile { InputStreamReadBytesResponse response = await inputStream.readBytes(1024); while (response.returnValue != -1) { yield response.bytes; - response = await inputStream.readBytes(1024); + response = await inputStream.readBytes(4 * 1024); } } else { throw _createNullInputStreamError(); @@ -61,7 +61,10 @@ base class AndroidXFile extends PlatformXFile { Future canRead() => _documentFile.canRead(); @override - Future exists() => _documentFile.exists(); + Future exists() { + // TODO: shoulc also call _documentFile.isFile + return _documentFile.exists(); + } UnsupportedError _createNullInputStreamError() { return UnsupportedError( diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index b8aa7a205951..321033b316da 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -1,7 +1,7 @@ // Platform Implementation for Android import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import '../cross_file_android.dart'; +import 'android_cross_file.dart'; final class CrossFileAndroid extends CrossFilePlatform { static void registerWith() { diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig index 592ceee85b89..ec97fc6f3021 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig +++ b/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig index 592ceee85b89..c4855bfe2000 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig +++ b/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_ios/example/ios/Podfile b/packages/cross_file/cross_file_ios/example/ios/Podfile new file mode 100644 index 000000000000..620e46eba607 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift similarity index 90% rename from packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift rename to packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift index a68b0e4ab79d..f411594f8a85 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIosPlugin.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift @@ -1,7 +1,7 @@ import Flutter import UIKit -public class CrossFileIosPlugin: NSObject, FlutterPlugin { +public class CrossFileIOSPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "cross_file_ios", binaryMessenger: registrar.messenger()) let instance = CrossFileIosPlugin() diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart index 405e5c816f59..6000f7421785 100644 --- a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart +++ b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart @@ -1,8 +1,4 @@ - -import 'cross_file_ios_platform_interface.dart'; - -class CrossFileIos { - Future getPlatformVersion() { - return CrossFileIosPlatform.instance.getPlatformVersion(); - } -} +export 'src/ios_cross_file.dart'; +export 'src/cross_file_ios.dart'; +export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' + show PlatformXFileCreationParams; diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart deleted file mode 100644 index d9b2a95634ba..000000000000 --- a/packages/cross_file/cross_file_ios/lib/cross_file_ios_method_channel.dart +++ /dev/null @@ -1,17 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -import 'cross_file_ios_platform_interface.dart'; - -/// An implementation of [CrossFileIosPlatform] that uses method channels. -class MethodChannelCrossFileIos extends CrossFileIosPlatform { - /// The method channel used to interact with the native platform. - @visibleForTesting - final methodChannel = const MethodChannel('cross_file_ios'); - - @override - Future getPlatformVersion() async { - final version = await methodChannel.invokeMethod('getPlatformVersion'); - return version; - } -} diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart deleted file mode 100644 index b89b622ac789..000000000000 --- a/packages/cross_file/cross_file_ios/lib/cross_file_ios_platform_interface.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -import 'cross_file_ios_method_channel.dart'; - -abstract class CrossFileIosPlatform extends PlatformInterface { - /// Constructs a CrossFileIosPlatform. - CrossFileIosPlatform() : super(token: _token); - - static final Object _token = Object(); - - static CrossFileIosPlatform _instance = MethodChannelCrossFileIos(); - - /// The default instance of [CrossFileIosPlatform] to use. - /// - /// Defaults to [MethodChannelCrossFileIos]. - static CrossFileIosPlatform get instance => _instance; - - /// Platform-specific implementations should set this with their own - /// platform-specific class that extends [CrossFileIosPlatform] when - /// they register themselves. - static set instance(CrossFileIosPlatform instance) { - PlatformInterface.verifyToken(instance, _token); - _instance = instance; - } - - Future getPlatformVersion() { - throw UnimplementedError('platformVersion() has not been implemented.'); - } -} diff --git a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart new file mode 100644 index 000000000000..f79429dfe51d --- /dev/null +++ b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart @@ -0,0 +1,15 @@ +// Platform Implementation for Android +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'ios_cross_file.dart'; + +final class CrossFileIOS extends CrossFilePlatform { + static void registerWith() { + CrossFilePlatform.instance = CrossFileIOS(); + } + + @override + IOSXFile createPlatformXFile(PlatformXFileCreationParams params) { + return IOSXFile(params); + } +} diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart new file mode 100644 index 000000000000..05c6fae1434c --- /dev/null +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -0,0 +1,71 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +base class IOSXFile extends PlatformXFile { + IOSXFile(super.params) : super.implementation(); + + late final DocumentFile _documentFile = DocumentFile.fromSingleUri( + path: params.path, + ); + + late final ContentResolver _contentResolver = ContentResolver.instance; + + @override + Future lastModified() async { + return DateTime.fromMillisecondsSinceEpoch( + await _documentFile.lastModified(), + ); + } + + @override + Future length() => _documentFile.length(); + + @override + Stream openRead([int? start, int? end]) async* { + final InputStream? inputStream = await _contentResolver.openInputStream( + params.path, + ); + // TODO: add support for start and end. + if (inputStream case InputStream inputStream) { + InputStreamReadBytesResponse response = await inputStream.readBytes(1024); + while (response.returnValue != -1) { + yield response.bytes; + response = await inputStream.readBytes(1024); + } + } else { + throw _createNullInputStreamError(); + } + } + + @override + Future readAsBytes() async { + final InputStream? inputStream = await _contentResolver.openInputStream( + params.path, + ); + if (inputStream case InputStream inputStream) { + return inputStream.readAllBytes(); + } + + throw _createNullInputStreamError(); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + return utf8.decodeStream(openRead()); + } + + @override + Future canRead() => _documentFile.canRead(); + + @override + Future exists() => _documentFile.exists(); + + UnsupportedError _createNullInputStreamError() { + return UnsupportedError( + 'Failed to get native InputStream from file with path: ${params.path}. ' + 'App may not have permissions to access file.', + ); + } +} diff --git a/packages/cross_file/cross_file_ios/pubspec.yaml b/packages/cross_file/cross_file_ios/pubspec.yaml index b4e13960a004..46a33257f7b6 100644 --- a/packages/cross_file/cross_file_ios/pubspec.yaml +++ b/packages/cross_file/cross_file_ios/pubspec.yaml @@ -1,69 +1,30 @@ name: cross_file_ios description: "A new Flutter plugin project." version: 0.0.1 -homepage: +publish_to: none environment: - sdk: ^3.10.0-200.0.dev - flutter: '>=3.3.0' + sdk: ^3.9.0 + flutter: ">=3.35.0" + +flutter: + plugin: + implements: cross_file + platforms: + ios: + pluginClass: CrossFileIOSPlugin + dartPluginClass: CrossFileIOS + android: + package: dev.flutter.packages.cross_file_android + pluginClass: CrossFileAndroidPlugin + dartPluginClass: CrossFileAndroid dependencies: flutter: sdk: flutter - plugin_platform_interface: ^2.0.2 + cross_file_platform_interface: + path: ../cross_file_platform_interface dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - # This section identifies this Flutter project as a plugin project. - # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) - # which should be registered in the plugin registry. This is required for - # using method channels. - # The Android 'package' specifies package in which the registered class is. - # This is required for using method channels on Android. - # The 'ffiPlugin' specifies that native code should be built and bundled. - # This is required for using `dart:ffi`. - # All these are used by the tooling to maintain consistency when - # adding or updating assets for this project. - plugin: - platforms: - ios: - pluginClass: CrossFileIosPlugin - - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # To add custom fonts to your plugin package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/to/font-from-package From 2196e7467490b4fdc630692042fec045762d0055 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 15 Nov 2025 12:02:11 -0600 Subject: [PATCH 016/398] add files --- .../ios/Runner.xcodeproj/project.pbxproj | 112 ++++++++++++++++++ .../cross_file_ios/example/lib/main.dart | 33 +----- .../ios/Classes/CrossFileIOSPlugin.swift | 2 +- .../lib/src/ios_cross_file.dart | 62 ++-------- .../cross_file_ios/pigeons/copyright.txt | 3 + .../cross_file_ios/pigeons/foundation.dart | 17 +++ .../cross_file/cross_file_ios/pubspec.yaml | 9 +- 7 files changed, 151 insertions(+), 87 deletions(-) create mode 100644 packages/cross_file/cross_file_ios/pigeons/copyright.txt create mode 100644 packages/cross_file/cross_file_ios/pigeons/foundation.dart diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj index 334602436974..3d6c9f4f3d89 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -10,7 +10,9 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 65AF3F910C52DB6D2F3DAE9D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A33FE71D0C42047E84BBCBE6 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 829E1B841CA9DB7260DC4C16 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E33381F0C94153C78C1AFE19 /* Pods_RunnerTests.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -40,14 +42,17 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 078A54601D0283091B1185EA /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2E1AE5E5601D04A21C0626B7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 8ADA6E46E97DBE1D2BD49E1E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -55,6 +60,11 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A33FE71D0C42047E84BBCBE6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C13A5126E08748B2929C82F3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + C2EAF8DCAE4A5A64E43C3680 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + E33381F0C94153C78C1AFE19 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E3676B09D7617ECB65174B4A /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,6 +72,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 65AF3F910C52DB6D2F3DAE9D /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A190650AD74D9C6C68DDAEF2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 829E1B841CA9DB7260DC4C16 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -76,6 +95,29 @@ path = RunnerTests; sourceTree = ""; }; + 77684829B5428D1CBC39FB7E /* Pods */ = { + isa = PBXGroup; + children = ( + C13A5126E08748B2929C82F3 /* Pods-Runner.debug.xcconfig */, + 2E1AE5E5601D04A21C0626B7 /* Pods-Runner.release.xcconfig */, + C2EAF8DCAE4A5A64E43C3680 /* Pods-Runner.profile.xcconfig */, + E3676B09D7617ECB65174B4A /* Pods-RunnerTests.debug.xcconfig */, + 078A54601D0283091B1185EA /* Pods-RunnerTests.release.xcconfig */, + 8ADA6E46E97DBE1D2BD49E1E /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; + 8FB841B256507B5BDE364A3A /* Frameworks */ = { + isa = PBXGroup; + children = ( + A33FE71D0C42047E84BBCBE6 /* Pods_Runner.framework */, + E33381F0C94153C78C1AFE19 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -94,6 +136,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + 77684829B5428D1CBC39FB7E /* Pods */, + 8FB841B256507B5BDE364A3A /* Frameworks */, ); sourceTree = ""; }; @@ -128,8 +172,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + E2980696C569222F2BFF4B05 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + A190650AD74D9C6C68DDAEF2 /* Frameworks */, ); buildRules = ( ); @@ -145,12 +191,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + A469FFB3E7F2610761EABEE5 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 138C88CB6F339C47BACAD73B /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -222,6 +270,23 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 138C88CB6F339C47BACAD73B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -253,6 +318,50 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + A469FFB3E7F2610761EABEE5 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E2980696C569222F2BFF4B05 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -379,6 +488,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E3676B09D7617ECB65174B4A /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -396,6 +506,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 078A54601D0283091B1185EA /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -411,6 +522,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 8ADA6E46E97DBE1D2BD49E1E /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/cross_file/cross_file_ios/example/lib/main.dart b/packages/cross_file/cross_file_ios/example/lib/main.dart index 80109a0a4cdf..e04612320022 100644 --- a/packages/cross_file/cross_file_ios/example/lib/main.dart +++ b/packages/cross_file/cross_file_ios/example/lib/main.dart @@ -16,37 +16,6 @@ class MyApp extends StatefulWidget { } class _MyAppState extends State { - String _platformVersion = 'Unknown'; - final _crossFileIosPlugin = CrossFileIos(); - - @override - void initState() { - super.initState(); - initPlatformState(); - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - String platformVersion; - // Platform messages may fail, so we use a try/catch PlatformException. - // We also handle the message potentially returning null. - try { - platformVersion = - await _crossFileIosPlugin.getPlatformVersion() ?? 'Unknown platform version'; - } on PlatformException { - platformVersion = 'Failed to get platform version.'; - } - - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; - - setState(() { - _platformVersion = platformVersion; - }); - } - @override Widget build(BuildContext context) { return MaterialApp( @@ -55,7 +24,7 @@ class _MyAppState extends State { title: const Text('Plugin example app'), ), body: Center( - child: Text('Running on: $_platformVersion\n'), + child: Text('Running on: \n'), ), ), ); diff --git a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift index f411594f8a85..65a3a5acf83c 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift @@ -4,7 +4,7 @@ import UIKit public class CrossFileIOSPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { let channel = FlutterMethodChannel(name: "cross_file_ios", binaryMessenger: registrar.messenger()) - let instance = CrossFileIosPlugin() + let instance = CrossFileIOSPlugin() registrar.addMethodCallDelegate(instance, channel: channel) } diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index 05c6fae1434c..7ae96ab6809e 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -6,66 +6,28 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart base class IOSXFile extends PlatformXFile { IOSXFile(super.params) : super.implementation(); - late final DocumentFile _documentFile = DocumentFile.fromSingleUri( - path: params.path, - ); - - late final ContentResolver _contentResolver = ContentResolver.instance; - @override - Future lastModified() async { - return DateTime.fromMillisecondsSinceEpoch( - await _documentFile.lastModified(), - ); + Future canRead() { + // TODO: implement canRead + throw UnimplementedError(); } @override - Future length() => _documentFile.length(); - - @override - Stream openRead([int? start, int? end]) async* { - final InputStream? inputStream = await _contentResolver.openInputStream( - params.path, - ); - // TODO: add support for start and end. - if (inputStream case InputStream inputStream) { - InputStreamReadBytesResponse response = await inputStream.readBytes(1024); - while (response.returnValue != -1) { - yield response.bytes; - response = await inputStream.readBytes(1024); - } - } else { - throw _createNullInputStreamError(); - } + Future exists() { + // TODO: implement exists + throw UnimplementedError(); } @override - Future readAsBytes() async { - final InputStream? inputStream = await _contentResolver.openInputStream( - params.path, - ); - if (inputStream case InputStream inputStream) { - return inputStream.readAllBytes(); - } - - throw _createNullInputStreamError(); + Future lastModified() { + // TODO: implement lastModified + throw UnimplementedError(); } @override - Future readAsString({Encoding encoding = utf8}) { - return utf8.decodeStream(openRead()); + Future length() { + // TODO: implement length + throw UnimplementedError(); } - @override - Future canRead() => _documentFile.canRead(); - - @override - Future exists() => _documentFile.exists(); - - UnsupportedError _createNullInputStreamError() { - return UnsupportedError( - 'Failed to get native InputStream from file with path: ${params.path}. ' - 'App may not have permissions to access file.', - ); - } } diff --git a/packages/cross_file/cross_file_ios/pigeons/copyright.txt b/packages/cross_file/cross_file_ios/pigeons/copyright.txt new file mode 100644 index 000000000000..07e5f8598a80 --- /dev/null +++ b/packages/cross_file/cross_file_ios/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart new file mode 100644 index 000000000000..2d9acbffcfb7 --- /dev/null +++ b/packages/cross_file/cross_file_ios/pigeons/foundation.dart @@ -0,0 +1,17 @@ +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/foundation.g.dart', + swiftOut: 'ios/Classes/proxies/Foundation.swift', + kotlinOut: + 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt', + kotlinOptions: KotlinOptions( + package: 'dev.flutter.packages.cross_file_android.proxies', + ), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +abstract class A { + +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_ios/pubspec.yaml b/packages/cross_file/cross_file_ios/pubspec.yaml index 46a33257f7b6..bedb0db2f23f 100644 --- a/packages/cross_file/cross_file_ios/pubspec.yaml +++ b/packages/cross_file/cross_file_ios/pubspec.yaml @@ -14,16 +14,17 @@ flutter: ios: pluginClass: CrossFileIOSPlugin dartPluginClass: CrossFileIOS - android: - package: dev.flutter.packages.cross_file_android - pluginClass: CrossFileAndroidPlugin - dartPluginClass: CrossFileAndroid dependencies: flutter: sdk: flutter cross_file_platform_interface: path: ../cross_file_platform_interface + pigeon: + git: + url: git@github.com:bparrishMines/packages.git + ref: pigeon_helper + path: packages/pigeon dev_dependencies: flutter_test: From f8528c94c717039ce898c321d422ccbfec1aa7a9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 15 Nov 2025 12:47:55 -0600 Subject: [PATCH 017/398] ios impl compiles --- .../lib/src/android_cross_file.dart | 8 +- .../ios/RunnerTests/FileManagerTests.swift | 67 ++ .../example/ios/RunnerTests/UrlTests.swift | 12 + .../ios/Classes/CrossFileIOSPlugin.swift | 28 +- .../ios/Classes/ProxyAPIDelegate.swift | 22 + .../proxies/FileManagerProxyAPIDelegate.swift | 33 + .../ios/Classes/proxies/Foundation.g.swift | 883 ++++++++++++++++++ .../Classes/proxies/UrlProxyAPIDelegate.swift | 20 + .../cross_file_ios/lib/src/foundation.g.dart | 807 ++++++++++++++++ .../lib/src/ios_cross_file.dart | 40 +- .../cross_file_ios/pigeons/foundation.dart | 27 +- .../lib/src/cross_file_platform.dart | 9 + .../lib/src/platform_cross_file.dart | 12 +- .../platform_shared_storage_cross_file.dart | 21 +- 14 files changed, 1955 insertions(+), 34 deletions(-) create mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift create mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift create mode 100644 packages/cross_file/cross_file_ios/lib/src/foundation.g.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index 7492939adb5d..480d3f4ee692 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -4,7 +4,7 @@ import 'dart:typed_data'; import 'package:cross_file_android/src/document_file.g.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -base class AndroidXFile extends PlatformXFile { +base class AndroidXFile extends PlatformSharedStorageXFile { AndroidXFile(super.params) : super.implementation(); late final DocumentFile _documentFile = DocumentFile.fromSingleUri( @@ -72,4 +72,10 @@ base class AndroidXFile extends PlatformXFile { 'App may not have permissions to access file.', ); } + + @override + Future delete() { + // TODO: implement delete + throw UnimplementedError(); + } } diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift new file mode 100644 index 000000000000..cc9f5db3c4f2 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift @@ -0,0 +1,67 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import Flutter +import XCTest + +@testable import cross_file_ios + +class FileManagerTests: XCTestCase { + func testFileExistsAtPath() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let path = "myString" + let value = try? api.pigeonDelegate.fileExistsAtPath(pigeonApi: api, pigeonInstance: instance, path: path) + + XCTAssertEqual(instance.fileExistsAtPathArgs, [path]) + XCTAssertEqual(value, instance.fileExistsAtPath(path: path)) + } + + func testIsReadableFileAtPath() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let path = "myString" + let value = try? api.pigeonDelegate.isReadableFileAtPath(pigeonApi: api, pigeonInstance: instance, path: path) + + XCTAssertEqual(instance.isReadableFileAtPathArgs, [path]) + XCTAssertEqual(value, instance.isReadableFileAtPath(path: path)) + } + + func testContentsAtPath() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let path = "myString" + let value = try? api.pigeonDelegate.contentsAtPath(pigeonApi: api, pigeonInstance: instance, path: path) + + XCTAssertEqual(instance.contentsAtPathArgs, [path]) + XCTAssertEqual(value, instance.contentsAtPath(path: path)) + } + +} +class TestFileManager: FileManager { + var fileExistsAtPathArgs: [AnyHashable?]? = nil + var isReadableFileAtPathArgs: [AnyHashable?]? = nil + var contentsAtPathArgs: [AnyHashable?]? = nil + + + override func fileExistsAtPath() { + fileExistsAtPathArgs = [path] + return true + } + override func isReadableFileAtPath() { + isReadableFileAtPathArgs = [path] + return true + } + override func contentsAtPath() { + contentsAtPathArgs = [path] + return byteArrayOf(0xA1.toByte()) + } +} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift new file mode 100644 index 000000000000..803f16043218 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift @@ -0,0 +1,12 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class URLTests: XCTestCase { +} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift index 65a3a5acf83c..14c550c01001 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift @@ -2,18 +2,22 @@ import Flutter import UIKit public class CrossFileIOSPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "cross_file_ios", binaryMessenger: registrar.messenger()) - let instance = CrossFileIOSPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } + var proxyApiRegistrar: FoundationPigeonProxyApiRegistrar? - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - result("iOS " + UIDevice.current.systemVersion) - default: - result(FlutterMethodNotImplemented) + init(binaryMessenger: FlutterBinaryMessenger) { + proxyApiRegistrar = FoundationPigeonProxyApiRegistrar( + binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) + proxyApiRegistrar?.setUp() + } + + public static func register(with registrar: FlutterPluginRegistrar) { + let plugin = CrossFileIOSPlugin(binaryMessenger: registrar.messenger()) + registrar.publish(plugin) + } + + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + proxyApiRegistrar!.ignoreCallsToDart = true + proxyApiRegistrar!.tearDown() + proxyApiRegistrar = nil } - } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift new file mode 100644 index 000000000000..2d2b1b2b996f --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift @@ -0,0 +1,22 @@ +import Foundation + +/// Implementation of `FoundationPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation +/// and any additional resources needed by an implementation. +open class ProxyApiDelegate: FoundationPigeonProxyApiDelegate { + /// Creates an error when the constructor of a class returns null. + func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { + return PigeonError( + code: "ConstructorReturnedNullError", + message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", + details: nil) + } + + func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL { + return PigeonApiURL(pigeonRegistrar: registrar, delegate: URLProxyAPIDelegate()) + } + + func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager { + return PigeonApiFileManager(pigeonRegistrar: registrar, delegate: FileManagerProxyAPIDelegate()) + } +} + diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift new file mode 100644 index 000000000000..f191549649ae --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift @@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation +import Flutter + +/// ProxyApi implementation for `FileManager`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { + func defaultManager(pigeonApi: PigeonApiFileManager) -> FileManager { + return FileManager.default + } + + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.fileExists(atPath: atPath) + } + + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.isReadableFile(atPath: atPath) + } + + func contents(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> FlutterStandardTypedData? { + let data = pigeonInstance.contents(atPath: atPath) + if let data = data { + return FlutterStandardTypedData(bytes: data) + } + + return nil + } +} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift new file mode 100644 index 000000000000..3f9ec29f2ccf --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift @@ -0,0 +1,883 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func createConnectionError(withChannelName channelName: String) -> PigeonError { + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +/// Handles the callback when an object is deallocated. +protocol FoundationPigeonInternalFinalizerDelegate: AnyObject { + /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. + func onDeinit(identifier: Int64) +} + + +// Attaches to an object to receive a callback when the object is deallocated. +internal final class FoundationPigeonInternalFinalizer { + internal static let associatedObjectKey = malloc(1)! + + private let identifier: Int64 + // Reference to the delegate is weak because the callback should be ignored if the + // `InstanceManager` is deallocated. + internal weak var delegate: FoundationPigeonInternalFinalizerDelegate? + + private init(identifier: Int64, delegate: FoundationPigeonInternalFinalizerDelegate) { + self.identifier = identifier + self.delegate = delegate + } + + internal static func attach( + to instance: AnyObject, identifier: Int64, delegate: FoundationPigeonInternalFinalizerDelegate + ) { + let finalizer = FoundationPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) + } + + static func detach(from instance: AnyObject) { + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? FoundationPigeonInternalFinalizer + if let finalizer = finalizer { + finalizer.delegate = nil + objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) + } + } + + deinit { + delegate?.onDeinit(identifier: identifier) + } +} + + +/// Maintains instances used to communicate with the corresponding objects in Dart. +/// +/// Objects stored in this container are represented by an object in Dart that is also stored in +/// an InstanceManager with the same identifier. +/// +/// When an instance is added with an identifier, either can be used to retrieve the other. +/// +/// Added instances are added as a weak reference and a strong reference. When the strong +/// reference is removed and the weak reference is deallocated,`FoundationPigeonInternalFinalizerDelegate.onDeinit` +/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is +/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), +/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually +/// again. +/// +/// Accessing and inserting to an InstanceManager is thread safe. +final class FoundationPigeonInstanceManager { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private static let minHostCreatedIdentifier: Int64 = 65536 + + private let lockQueue = DispatchQueue(label: "FoundationPigeonInstanceManager") + private let identifiers: NSMapTable = NSMapTable( + keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) + private let weakInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) + private let strongInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) + private let finalizerDelegate: FoundationPigeonInternalFinalizerDelegate + private var nextIdentifier: Int64 = minHostCreatedIdentifier + + public init(finalizerDelegate: FoundationPigeonInternalFinalizerDelegate) { + self.finalizerDelegate = finalizerDelegate + } + + /// Adds a new instance that was instantiated from Dart. + /// + /// The same instance can be added multiple times, but each identifier must be unique. This allows + /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. + /// + /// - Parameters: + /// - instance: the instance to be stored + /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique + func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + lockQueue.async { + self.addInstance(instance, withIdentifier: identifier) + } + } + + /// Adds a new instance that was instantiated from the host platform. + /// + /// - Parameters: + /// - instance: the instance to be stored. This must be unique to all other added instances. + /// - Returns: the unique identifier (>= 0) stored with instance + func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { + assert(!containsInstance(instance), "Instance of \(instance) has already been added.") + var identifier: Int64 = -1 + lockQueue.sync { + identifier = nextIdentifier + nextIdentifier += 1 + self.addInstance(instance, withIdentifier: identifier) + } + return identifier + } + + /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier paired to an instance. + /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if + /// the manager doesn't contain the value + func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) + strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + /// Retrieves the instance associated with identifier. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier associated with an instance + /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func instance(forIdentifier instanceIdentifier: Int64) -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + assert(identifier >= 0) + assert( + weakInstances.object(forKey: identifier as NSNumber) == nil, + "Identifier has already been added: \(identifier)") + identifiers.setObject(NSNumber(value: identifier), forKey: instance) + weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) + strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) + FoundationPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + } + + /// Retrieves the identifier paired with an instance. + /// + /// If the manager contains a strong reference to `instance`, it will return the identifier + /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new + /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. + /// + /// If this method returns a nonnull identifier, this method also expects the Dart + /// `FoundationPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + /// identifier is associated with. + /// + /// - Parameters: + /// - instance: an instance that may be stored in the manager + /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { + var identifier: Int64? = nil + lockQueue.sync { + if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { + strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) + identifier = existingIdentifier + } + } + return identifier + } + + /// Whether this manager contains the given `instance`. + /// + /// - Parameters: + /// - instance: the instance whose presence in this manager is to be tested + /// - Returns: whether this manager contains the given `instance` + func containsInstance(_ instance: AnyObject) -> Bool { + var containsInstance = false + lockQueue.sync { + containsInstance = identifiers.object(forKey: instance) != nil + } + return containsInstance + } + + /// Removes all of the instances from this manager. + /// + /// The manager will be empty after this call returns. + func removeAllObjects() throws { + lockQueue.sync { + let weakInstancesEnumerator = weakInstances.objectEnumerator()! + while let instance = weakInstancesEnumerator.nextObject() { + FoundationPigeonInternalFinalizer.detach(from: instance as AnyObject) + } + identifiers.removeAllObjects() + weakInstances.removeAllObjects() + strongInstances.removeAllObjects() + nextIdentifier = FoundationPigeonInstanceManager.minHostCreatedIdentifier + } + } + + /// The number of instances stored as a strong reference. + /// + /// For debugging and testing purposes. + internal var strongInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = strongInstances.count + } + return count + } + + /// The number of instances stored as a weak reference. + /// + /// For debugging and testing purposes. NSMapTables that store keys or objects as weak + /// reference will be reclaimed non-deterministically. + internal var weakInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = weakInstances.count + } + return count + } +} + + +private class FoundationPigeonInstanceManagerApi { + /// The codec used for serializing messages. + var codec: FlutterStandardMessageCodec { FoundationPigeonCodec.shared } + + /// Handles sending and receiving messages with Dart. + unowned let binaryMessenger: FlutterBinaryMessenger + + init(binaryMessenger: FlutterBinaryMessenger) { + self.binaryMessenger = binaryMessenger + } + + /// Sets up an instance of `FoundationPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: FoundationPigeonInstanceManager?) { + let codec = FoundationPigeonCodec.shared + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + removeStrongReferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! Int64 + do { + let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeStrongReferenceChannel.setMessageHandler(nil) + } + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + clearChannel.setMessageHandler { _, reply in + do { + try instanceManager.removeAllObjects() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearChannel.setMessageHandler(nil) + } + } + + /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([identifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } +} +protocol FoundationPigeonProxyApiDelegate { + /// An implementation of [PigeonApiURL] used to add a new Dart instance of + /// `URL` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL + /// An implementation of [PigeonApiFileManager] used to add a new Dart instance of + /// `FileManager` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager +} + +open class FoundationPigeonProxyApiRegistrar { + let binaryMessenger: FlutterBinaryMessenger + let apiDelegate: FoundationPigeonProxyApiDelegate + let instanceManager: FoundationPigeonInstanceManager + /// Whether APIs should ignore calling to Dart. + public var ignoreCallsToDart = false + private var _codec: FlutterStandardMessageCodec? + var codec: FlutterStandardMessageCodec { + if _codec == nil { + _codec = FlutterStandardMessageCodec( + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + } + return _codec! + } + + private class InstanceManagerApiFinalizerDelegate: FoundationPigeonInternalFinalizerDelegate { + let api: FoundationPigeonInstanceManagerApi + + init(_ api: FoundationPigeonInstanceManagerApi) { + self.api = api + } + + public func onDeinit(identifier: Int64) { + api.removeStrongReference(identifier: identifier) { + _ in + } + } + } + + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: FoundationPigeonProxyApiDelegate) { + self.binaryMessenger = binaryMessenger + self.apiDelegate = apiDelegate + self.instanceManager = FoundationPigeonInstanceManager( + finalizerDelegate: InstanceManagerApiFinalizerDelegate( + FoundationPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) + } + + func setUp() { + FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiURL(self)) + PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileManager(self)) + } + func tearDown() { + FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + } +} +private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + + private class FoundationPigeonInternalProxyApiCodecReader: FoundationPigeonCodecReader { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + + init(data: Data, pigeonRegistrar: FoundationPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + let identifier = self.readValue() + let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( + forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) + if instance == nil { + print("Failed to find instance with identifier: \(identifier!)") + } + return instance + default: + return super.readValue(ofType: type) + } + } + } + + private class FoundationPigeonInternalProxyApiCodecWriter: FoundationPigeonCodecWriter { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + + init(data: NSMutableData, pigeonRegistrar: FoundationPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func writeValue(_ value: Any) { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + super.writeValue(value) + return + } + + + if let instance = value as? URL { + pigeonRegistrar.apiDelegate.pigeonApiURL(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + + if let instance = value as? FileManager { + pigeonRegistrar.apiDelegate.pigeonApiFileManager(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + { + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) + } else { + print("Unsupported value: \(value) of \(type(of: value))") + assert(false, "Unsupported value for FoundationPigeonInternalProxyApiCodecWriter") + } + + } + } + + init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + } + + override func reader(with data: Data) -> FlutterStandardReader { + return FoundationPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return FoundationPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + } +} + +private class FoundationPigeonCodecReader: FlutterStandardReader { +} + +private class FoundationPigeonCodecWriter: FlutterStandardWriter { +} + +private class FoundationPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return FoundationPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return FoundationPigeonCodecWriter(data: data) + } +} + +class FoundationPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = FoundationPigeonCodec(readerWriter: FoundationPigeonCodecReaderWriter()) +} + +protocol PigeonApiDelegateURL { + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws -> Bool + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws +} + +protocol PigeonApiProtocolURL { +} + +final class PigeonApiURL: PigeonApiProtocolURL { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateURL + init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateURL) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiURL?) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + } + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + try api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, url: urlArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of URL and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: URL, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + } +} + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + + + +/// ProxyApi implementation for `URL`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class URLProxyAPIDelegate : PigeonApiDelegateURL { + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws -> Bool { + return URL.startAccessingSecurityScopedResource(url: url) + } + + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws { + URL.stopAccessingSecurityScopedResource(url: url) + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class URLTests: XCTestCase { +} +*/ + +protocol PigeonApiDelegateFileManager { + func defaultManager(pigeonApi: PigeonApiFileManager) throws -> FileManager + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool + func contents(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> FlutterStandardTypedData? +} + +protocol PigeonApiProtocolFileManager { +} + +final class PigeonApiFileManager: PigeonApiProtocolFileManager { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateFileManager + init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileManager) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileManager?) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let defaultManagerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + defaultManagerChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] as! Int64 + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(try api.pigeonDelegate.defaultManager(pigeonApi: api), withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + defaultManagerChannel.setMessageHandler(nil) + } + let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileExists", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileExistsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileExistsChannel.setMessageHandler(nil) + } + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isReadableFileChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isReadableFileChannel.setMessageHandler(nil) + } + let contentsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.contents", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + contentsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.contents(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + contentsChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of FileManager and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: FileManager, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + } +} + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + + + +/// ProxyApi implementation for `FileManager`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { + func defaultManager(pigeonApi: PigeonApiFileManager): FileManager { + return FileManager.defaultManager + } + + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.fileExists(atPath: atPath) + } + + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.isReadableFile(atPath: atPath) + } + + func contents(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> FlutterStandardTypedData? { + return pigeonInstance.contents(atPath: atPath) + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class FileManagerTests: XCTestCase { + func testFileExists() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.fileExistsArgs, [atPath]) + XCTAssertEqual(value, instance.fileExists(atPath: atPath)) + } + + func testIsReadableFile() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.isReadableFileArgs, [atPath]) + XCTAssertEqual(value, instance.isReadableFile(atPath: atPath)) + } + + func testContents() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.contents(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.contentsArgs, [atPath]) + XCTAssertEqual(value, instance.contents(atPath: atPath)) + } + +} +class TestFileManager: FileManager { + var fileExistsArgs: [AnyHashable?]? = nil + var isReadableFileArgs: [AnyHashable?]? = nil + var contentsArgs: [AnyHashable?]? = nil + + + override func fileExists() { + fileExistsArgs = [atPath] + return true + } + override func isReadableFile() { + isReadableFileArgs = [atPath] + return true + } + override func contents() { + contentsArgs = [atPath] + return byteArrayOf(0xA1.toByte()) + } +} +*/ + diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift new file mode 100644 index 000000000000..385db6915d61 --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +/// ProxyApi implementation for `URL`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class URLProxyAPIDelegate : PigeonApiDelegateURL { + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws -> Bool { + return URL(string: url)!.startAccessingSecurityScopedResource() + } + + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws { + URL(string: url)!.stopAccessingSecurityScopedResource() + } + +} diff --git a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart new file mode 100644 index 000000000000..c38544e82f54 --- /dev/null +++ b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart @@ -0,0 +1,807 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:io' show Platform; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} +/// Provides overrides for the constructors and static members of each +/// Dart proxy class. +/// +/// This is only intended to be used with unit tests to prevent errors from +/// making message calls in a unit test. +/// +/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. +@visibleForTesting +class PigeonOverrides { + /// Overrides [FileManager.defaultManager]. + static FileManager? fileManager_defaultManager; + + /// Overrides [URL.startAccessingSecurityScopedResource]. + static Future Function(String)? + uRL_startAccessingSecurityScopedResource; + + /// Overrides [URL.stopAccessingSecurityScopedResource]. + static Future Function(String)? uRL_stopAccessingSecurityScopedResource; + + /// Sets all overridden ProxyApi class members to null. + static void pigeon_reset() { + uRL_startAccessingSecurityScopedResource = null; + uRL_stopAccessingSecurityScopedResource = null; + fileManager_defaultManager = null; + } +} + +/// An immutable object that serves as the base class for all Dart proxy classes +/// and can provide functional copies of itself. +/// +/// All implementers are expected to be [immutable] as defined by the annotation +/// and override [pigeon_copy] returning an instance of itself. +@immutable +abstract class PigeonInternalProxyApiBaseClass { + /// Construct a [PigeonInternalProxyApiBaseClass]. + PigeonInternalProxyApiBaseClass({ + this.pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) : pigeon_instanceManager = + pigeon_instanceManager ?? PigeonInstanceManager.instance; + + /// Sends and receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used, which routes to + /// the host platform. + @protected + final BinaryMessenger? pigeon_binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final PigeonInstanceManager pigeon_instanceManager; + + /// Instantiates and returns a functionally identical object to oneself. + /// + /// Outside of tests, this method should only ever be called by + /// [PigeonInstanceManager]. + /// + /// Subclasses should always override their parent's implementation of this + /// method. + @protected + PigeonInternalProxyApiBaseClass pigeon_copy(); +} + +/// Maintains instances used to communicate with the native objects they +/// represent. +/// +/// Added instances are stored as weak references and their copies are stored +/// as strong references to maintain access to their variables and callback +/// methods. Both are stored with the same identifier. +/// +/// When a weak referenced instance becomes inaccessible, +/// [onWeakReferenceRemoved] is called with its associated identifier. +/// +/// If an instance is retrieved and has the possibility to be used, +/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference +/// is added as a weak reference with the same identifier. This prevents a +/// scenario where the weak referenced instance was released and then later +/// returned by the host platform. +class PigeonInstanceManager { + /// Constructs a [PigeonInstanceManager]. + PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { + this.onWeakReferenceRemoved = (int identifier) { + _weakInstances.remove(identifier); + onWeakReferenceRemoved(identifier); + }; + _finalizer = Finalizer(this.onWeakReferenceRemoved); + } + + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously by the host platform. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + static const int _maxDartCreatedIdentifier = 65536; + + /// The default [PigeonInstanceManager] used by Dart proxy classes. + /// + /// On creation, this manager makes a call to clear the native + /// InstanceManager. This is to prevent identifier conflicts after a host + /// restart. + static final PigeonInstanceManager instance = _initInstance(); + + // Expando is used because it doesn't prevent its keys from becoming + // inaccessible. This allows the manager to efficiently retrieve an identifier + // of an instance without holding a strong reference to that instance. + // + // It also doesn't use `==` to search for identifiers, which would lead to an + // infinite loop when comparing an object to its copy. (i.e. which was caused + // by calling instanceManager.getIdentifier() inside of `==` while this was a + // HashMap). + final Expando _identifiers = Expando(); + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; + late final Finalizer _finalizer; + int _nextIdentifier = 0; + + /// Called when a weak referenced instance is removed by [removeWeakReference] + /// or becomes inaccessible. + late final void Function(int) onWeakReferenceRemoved; + + static PigeonInstanceManager _initInstance() { + if (Platform.environment['FLUTTER_TEST'] == 'true') { + return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + } + WidgetsFlutterBinding.ensureInitialized(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. + api.clear(); + final PigeonInstanceManager instanceManager = PigeonInstanceManager( + onWeakReferenceRemoved: (int identifier) { + api.removeStrongReference(identifier); + }, + ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + URL.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + FileManager.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + return instanceManager; + } + + /// Adds a new instance that was instantiated by Dart. + /// + /// In other words, Dart wants to add a new instance that will represent + /// an object that will be instantiated on the host platform. + /// + /// Throws assertion error if the instance has already been added. + /// + /// Returns the randomly generated id of the [instance] added. + int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { + assert(getIdentifier(instance) == null); + + final int identifier = _nextUniqueIdentifier(); + _identifiers[instance] = identifier; + _weakInstances[identifier] = + WeakReference(instance); + _finalizer.attach(instance, identifier, detach: instance); + + final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); + _identifiers[copy] = identifier; + _strongInstances[identifier] = copy; + return identifier; + } + + /// Removes the instance, if present, and call [onWeakReferenceRemoved] with + /// its identifier. + /// + /// Returns the identifier associated with the removed instance. Otherwise, + /// `null` if the instance was not found in this manager. + /// + /// This does not remove the strong referenced instance associated with + /// [instance]. This can be done with [remove]. + int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { + final int? identifier = getIdentifier(instance); + if (identifier == null) { + return null; + } + + _identifiers[instance] = null; + _finalizer.detach(instance); + onWeakReferenceRemoved(identifier); + + return identifier; + } + + /// Removes [identifier] and its associated strongly referenced instance, if + /// present, from the manager. + /// + /// Returns the strong referenced instance associated with [identifier] before + /// it was removed. Returns `null` if [identifier] was not associated with + /// any strong reference. + /// + /// Throws an `AssertionError` if the weak referenced instance associated with + /// [identifier] is not removed first. This can be done with + /// [removeWeakReference]. + T? remove(int identifier) { + final T? instance = _weakInstances[identifier]?.target as T?; + assert( + instance == null, + 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', + ); + return _strongInstances.remove(identifier) as T?; + } + + /// Retrieves the instance associated with identifier. + /// + /// The value returned is chosen from the following order: + /// + /// 1. A weakly referenced instance associated with identifier. + /// 2. If the only instance associated with identifier is a strongly + /// referenced instance, a copy of the instance is added as a weak reference + /// with the same identifier. Returning the newly created copy. + /// 3. If no instance is associated with identifier, returns null. + /// + /// This method also expects the host `InstanceManager` to have a strong + /// reference to the instance the identifier is associated with. + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + + if (weakInstance == null) { + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + if (strongInstance != null) { + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + _identifiers[copy] = identifier; + _weakInstances[identifier] = WeakReference(copy); + _finalizer.attach(copy, identifier, detach: copy); + return copy as T; + } + return strongInstance as T?; + } + + return weakInstance as T; + } + + /// Retrieves the identifier associated with instance. + int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { + return _identifiers[instance]; + } + + /// Adds a new instance that was instantiated by the host platform. + /// + /// In other words, the host platform wants to add a new instance that + /// represents an object on the host platform. Stored with [identifier]. + /// + /// Throws assertion error if the instance or its identifier has already been + /// added. + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + assert(!containsIdentifier(identifier)); + assert(getIdentifier(instance) == null); + assert(identifier >= 0); + + _identifiers[instance] = identifier; + _strongInstances[identifier] = instance; + } + + /// Whether this manager contains the given [identifier]. + bool containsIdentifier(int identifier) { + return _weakInstances.containsKey(identifier) || + _strongInstances.containsKey(identifier); + } + + int _nextUniqueIdentifier() { + late int identifier; + do { + identifier = _nextIdentifier; + _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; + } while (containsIdentifier(identifier)); + return identifier; + } +} + +/// Generated API for managing the Dart and native `PigeonInstanceManager`s. +class _PigeonInternalInstanceManagerApi { + /// Constructor for [_PigeonInternalInstanceManagerApi]. + _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) + : pigeonVar_binaryMessenger = binaryMessenger; + + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + static void setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? binaryMessenger, + PigeonInstanceManager? instanceManager, + }) { + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + try { + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future removeStrongReference(int identifier) async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + /// Clear the native `PigeonInstanceManager`. + /// + /// This is typically called after a hot restart. + Future clear() async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.clear'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } +} + +class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} + + + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} +class URL extends PigeonInternalProxyApiBaseClass { + /// Constructs [URL] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + URL.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecURL = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + URL Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + URL.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + static Future startAccessingSecurityScopedResource( + String url, { + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) async { + if (PigeonOverrides.uRL_startAccessingSecurityScopedResource != null) { + return PigeonOverrides.uRL_startAccessingSecurityScopedResource!(url); + } + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([url]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + static Future stopAccessingSecurityScopedResource( + String url, { + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) async { + if (PigeonOverrides.uRL_stopAccessingSecurityScopedResource != null) { + return PigeonOverrides.uRL_stopAccessingSecurityScopedResource!(url); + } + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([url]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + @override + URL pigeon_copy() { + return URL.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + +class FileManager extends PigeonInternalProxyApiBaseClass { + /// Constructs [FileManager] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + FileManager.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileManager = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static final FileManager _defaultManager = pigeonVar_defaultManager(); + + static FileManager get defaultManager => + PigeonOverrides.fileManager_defaultManager ?? _defaultManager; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + FileManager Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + FileManager.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + static FileManager pigeonVar_defaultManager() { + final FileManager pigeonVar_instance = FileManager.pigeon_detached(); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); + final BinaryMessenger pigeonVar_binaryMessenger = + ServicesBinding.instance.defaultBinaryMessenger; + final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance + .addDartCreatedInstance(pigeonVar_instance); + () async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + return pigeonVar_instance; + } + + Future fileExists(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.fileExists'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future isReadableFile(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future contents(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.contents'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as Uint8List?); + } + } + + @override + FileManager pigeon_copy() { + return FileManager.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index 7ae96ab6809e..b65a2225a709 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -1,11 +1,14 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'package:cross_file_ios/src/foundation.g.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -base class IOSXFile extends PlatformXFile { +base class IOSXFile extends PlatformSharedStorageXFile { IOSXFile(super.params) : super.implementation(); + final FileManager _fileManager = FileManager.defaultManager; + @override Future canRead() { // TODO: implement canRead @@ -14,8 +17,7 @@ base class IOSXFile extends PlatformXFile { @override Future exists() { - // TODO: implement exists - throw UnimplementedError(); + return _fileManager.fileExists(params.path); } @override @@ -30,4 +32,36 @@ base class IOSXFile extends PlatformXFile { throw UnimplementedError(); } + @override + Future delete() { + // TODO: implement delete + throw UnimplementedError(); + } + + @override + Stream> openRead([int? start, int? end]) { + // TODO: implement openRead + throw UnimplementedError(); + } + + @override + Future readAsBytes() async { + final bool canRead = await URL.startAccessingSecurityScopedResource(params.path); + if (canRead) { + final Uint8List? bytes = await _fileManager.contents(params.path); + URL.stopAccessingSecurityScopedResource(params.path); + + if (bytes case Uint8List bytes) { + return bytes; + } + } + + throw UnsupportedError('Can access bytes to file: ${params.path}'); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + // TODO: implement readAsString + throw UnimplementedError(); + } } diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart index 2d9acbffcfb7..39299c82865b 100644 --- a/packages/cross_file/cross_file_ios/pigeons/foundation.dart +++ b/packages/cross_file/cross_file_ios/pigeons/foundation.dart @@ -3,15 +3,28 @@ import 'package:pigeon/pigeon.dart'; @ConfigurePigeon( PigeonOptions( dartOut: 'lib/src/foundation.g.dart', - swiftOut: 'ios/Classes/proxies/Foundation.swift', - kotlinOut: - 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt', - kotlinOptions: KotlinOptions( - package: 'dev.flutter.packages.cross_file_android.proxies', - ), + swiftOut: 'ios/Classes/proxies/Foundation.g.swift', copyrightHeader: 'pigeons/copyright.txt', ), ) -abstract class A { +@ProxyApi() +abstract class URL { + @static + bool startAccessingSecurityScopedResource(String url); + + @static + void stopAccessingSecurityScopedResource(String url); +} + +@ProxyApi() +abstract class FileManager { + @static + late final FileManager defaultManager; + + bool fileExists(String atPath); + + bool isReadableFile(String atPath); + + Uint8List? contents(String atPath); } \ No newline at end of file diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 681ce9a7a2a9..d57c2e39d612 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -1,11 +1,20 @@ import 'platform_cross_directory.dart'; import 'platform_cross_file.dart'; +import 'shared_storage/platform_shared_storage_cross_file.dart'; abstract base class CrossFilePlatform { static CrossFilePlatform? instance; PlatformXFile createPlatformXFile(PlatformXFileCreationParams params); + PlatformSharedStorageXFile createPlatformSharedStorageXFile( + PlatformSharedStorageXFileCreationParams params, + ) { + throw UnimplementedError( + 'createPlatformSharedStorageXFile is not implemented on the current platform.', + ); + } + PlatformXDirectory createPlatformXDirectory( PlatformXDirectoryCreationParams params, ) { diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index dd853f91d2dc..34e105b00299 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -46,17 +46,11 @@ abstract base class PlatformXFile { Future canRead(); - Stream> openRead([int? start, int? end]) { - throw UnimplementedError(); - } + Stream> openRead([int? start, int? end]); /// Reads the entire file contents as a list of bytes. - Future readAsBytes() { - throw UnimplementedError(); - } + Future readAsBytes(); /// Reads the entire file contents as a string using the given Encoding. - Future readAsString({Encoding encoding = utf8}) { - throw UnimplementedError(); - } + Future readAsString({Encoding encoding = utf8}); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart index bcff9589bdd9..bcf267632bfd 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart @@ -11,8 +11,25 @@ base class PlatformSharedStorageXFileCreationParams mixin SharedStoragePlatformXFileExtension implements PlatformXFileExtension {} abstract base class PlatformSharedStorageXFile extends PlatformXFile { - PlatformSharedStorageXFile(PlatformSharedStorageXFileCreationParams params) - : super.implementation(params); + /// Creates a new [PlatformSharedStorageXFile] + factory PlatformSharedStorageXFile( + PlatformSharedStorageXFileCreationParams params, + ) { + assert( + CrossFilePlatform.instance != null, + 'A platform implementation for `cross_file` has not been set. Please ' + 'ensure that an implementation of `XFilePlatform` has been set to ' + '`CrossFilePlatform.instance` before use. For unit testing, ' + '`CrossFilePlatform.instance` can be set with your own test implementation.', + ); + final PlatformSharedStorageXFile file = CrossFilePlatform.instance! + .createPlatformSharedStorageXFile(params); + return file; + } + + @protected + PlatformSharedStorageXFile.implementation(super.params) + : super.implementation(); @override PlatformSharedStorageXFileCreationParams get params => From ae421ebf67e1accb48dd06232aef45f815bf22bf Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:25:28 -0600 Subject: [PATCH 018/398] update ios impl --- .../lib/src/android_cross_file.dart | 4 +- .../lib/src/cross_file_android.dart | 9 + .../ios/RunnerTests/FileHandleTests.swift | 39 +++ .../example/ios/RunnerTests/UrlTests.swift | 33 +++ .../ios/Classes/ProxyAPIDelegate.swift | 4 +- .../proxies/FileHandleProxyAPIDelegate.swift | 35 +++ .../proxies/FileManagerProxyAPIDelegate.swift | 33 --- .../ios/Classes/proxies/Foundation.g.swift | 243 +++++++++-------- ...legate.swift => URLProxyAPIDelegate.swift} | 14 +- .../cross_file_ios/lib/cross_file_ios.dart | 2 +- .../lib/src/cross_file_ios.dart | 9 + .../cross_file_ios/lib/src/foundation.g.dart | 256 +++++++++--------- .../lib/src/ios_cross_file.dart | 45 +-- .../cross_file_ios/pigeons/foundation.dart | 20 +- .../cross_file/cross_file_ios/pubspec.yaml | 8 +- .../platform_shared_storage_cross_file.dart | 11 +- .../ios/Runner.xcodeproj/project.pbxproj | 19 ++ .../xcshareddata/xcschemes/Runner.xcscheme | 2 + .../example/lib/open_text_page.dart | 18 +- .../file_selector_ios/example/pubspec.yaml | 2 + .../FileSelectorPlugin.swift | 21 ++ .../file_selector_ios/messages.g.swift | 40 ++- .../lib/file_selector_ios.dart | 16 ++ .../file_selector_ios/lib/src/messages.g.dart | 100 +++---- .../file_selector_ios/pigeons/messages.dart | 3 + .../file_selector_ios/pubspec.yaml | 2 + 26 files changed, 601 insertions(+), 387 deletions(-) create mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift rename packages/cross_file/cross_file_ios/ios/Classes/proxies/{UrlProxyAPIDelegate.swift => URLProxyAPIDelegate.swift} (65%) diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index 480d3f4ee692..aacda3e6a298 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -53,8 +53,8 @@ base class AndroidXFile extends PlatformSharedStorageXFile { } @override - Future readAsString({Encoding encoding = utf8}) { - return utf8.decodeStream(openRead()); + Future readAsString({Encoding encoding = utf8}) async { + return utf8.decode(await readAsBytes()); } @override diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index 321033b316da..ab54de262baf 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -10,6 +10,15 @@ final class CrossFileAndroid extends CrossFilePlatform { @override AndroidXFile createPlatformXFile(PlatformXFileCreationParams params) { + return createPlatformSharedStorageXFile( + PlatformSharedStorageXFileCreationParams(path: params.path), + ); + } + + @override + AndroidXFile createPlatformSharedStorageXFile( + PlatformSharedStorageXFileCreationParams params, + ) { return AndroidXFile(params); } } diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift new file mode 100644 index 000000000000..67dd7092dfc6 --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class FileHandleTests: XCTestCase { + func testFromReadingFromUrl() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = try? api.pigeonDelegate.fromReadingFromUrl(pigeonApi: api, url: TestURL) + XCTAssertNotNil(instance) + } + + func testReadToEnd() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = TestFileHandle() + let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.readToEndCalled) + XCTAssertEqual(value, instance.readToEnd()) + } + +} +class TestFileHandle: FileHandle { + var readToEndCalled = false + + + override func readToEnd() { + readToEndCalled = true + } +} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift index 803f16043218..4a556b3e015c 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift @@ -9,4 +9,37 @@ import XCTest @testable import cross_file_ios class URLTests: XCTestCase { + func testStartAccessingSecurityScopedResource() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + let value = try? api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.startAccessingSecurityScopedResourceCalled) + XCTAssertEqual(value, instance.startAccessingSecurityScopedResource()) + } + + func testStopAccessingSecurityScopedResource() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + try? api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.stopAccessingSecurityScopedResourceCalled) + } + +} +class TestURL: URL { + var startAccessingSecurityScopedResourceCalled = false + var stopAccessingSecurityScopedResourceCalled = false + + + override func startAccessingSecurityScopedResource() { + startAccessingSecurityScopedResourceCalled = true + } + override func stopAccessingSecurityScopedResource() { + stopAccessingSecurityScopedResourceCalled = true + } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift index 2d2b1b2b996f..19d2517d4ccf 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift @@ -15,8 +15,8 @@ open class ProxyApiDelegate: FoundationPigeonProxyApiDelegate { return PigeonApiURL(pigeonRegistrar: registrar, delegate: URLProxyAPIDelegate()) } - func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager { - return PigeonApiFileManager(pigeonRegistrar: registrar, delegate: FileManagerProxyAPIDelegate()) + func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle { + return PigeonApiFileHandle(pigeonRegistrar: registrar, delegate: FileHandleProxyAPIDelegate()) } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift new file mode 100644 index 000000000000..89f6900a3c24 --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import Foundation + +/// ProxyApi implementation for `FileHandle`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class FileHandleProxyAPIDelegate : PigeonApiDelegateFileHandle { + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle { + return try FileHandle(forReadingFrom: url) + } + + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? { + var bytes: Data? + if #available(iOS 13.4, *) { + bytes = try pigeonInstance.readToEnd() + } else { + bytes = pigeonInstance.readDataToEndOfFile() + } + + if let bytes = bytes { + return FlutterStandardTypedData(bytes: bytes) + } + + return nil + } + + func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { + try pigeonInstance.close() + } +} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift deleted file mode 100644 index f191549649ae..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation -import Flutter - -/// ProxyApi implementation for `FileManager`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { - func defaultManager(pigeonApi: PigeonApiFileManager) -> FileManager { - return FileManager.default - } - - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { - return pigeonInstance.fileExists(atPath: atPath) - } - - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { - return pigeonInstance.isReadableFile(atPath: atPath) - } - - func contents(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> FlutterStandardTypedData? { - let data = pigeonInstance.contents(atPath: atPath) - if let data = data { - return FlutterStandardTypedData(bytes: data) - } - - return nil - } -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift index 3f9ec29f2ccf..5896ec9aa766 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift @@ -366,9 +366,9 @@ protocol FoundationPigeonProxyApiDelegate { /// An implementation of [PigeonApiURL] used to add a new Dart instance of /// `URL` to the Dart `InstanceManager` and make calls to Dart. func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL - /// An implementation of [PigeonApiFileManager] used to add a new Dart instance of - /// `FileManager` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager + /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of + /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle } open class FoundationPigeonProxyApiRegistrar { @@ -411,12 +411,12 @@ open class FoundationPigeonProxyApiRegistrar { func setUp() { FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiURL(self)) - PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileManager(self)) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) } func tearDown() { FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { @@ -472,8 +472,8 @@ private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandard } - if let instance = value as? FileManager { - pigeonRegistrar.apiDelegate.pigeonApiFileManager(pigeonRegistrar).pigeonNewInstance( + if let instance = value as? FileHandle { + pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) @@ -530,8 +530,9 @@ class FoundationPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { } protocol PigeonApiDelegateURL { - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws -> Bool - func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws + func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws } protocol PigeonApiProtocolURL { @@ -550,13 +551,28 @@ final class PigeonApiURL: PigeonApiProtocolURL { ? FlutterStandardMessageCodec( readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() + let fileURLWithPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.fileURLWithPath", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileURLWithPathChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pathArg = args[0] as! String + do { + let result = try api.pigeonDelegate.fileURLWithPath(pigeonApi: api, path: pathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileURLWithPathChannel.setMessageHandler(nil) + } let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource", binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let urlArg = args[0] as! String + let pigeonInstanceArg = args[0] as! URL do { - let result = try api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, url: urlArg) + let result = try api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -569,9 +585,9 @@ final class PigeonApiURL: PigeonApiProtocolURL { if let api = api { stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let urlArg = args[0] as! String + let pigeonInstanceArg = args[0] as! URL do { - try api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, url: urlArg) + try api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -630,12 +646,16 @@ import Foundation /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. class URLProxyAPIDelegate : PigeonApiDelegateURL { - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws -> Bool { - return URL.startAccessingSecurityScopedResource(url: url) + func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? { + return URL.fileURLWithPath(path: path) + } + + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool { + return pigeonInstance.startAccessingSecurityScopedResource() } - func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws { - URL.stopAccessingSecurityScopedResource(url: url) + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws { + pigeonInstance.stopAccessingSecurityScopedResource() } } @@ -653,99 +673,116 @@ import XCTest @testable import cross_file_ios class URLTests: XCTestCase { + func testStartAccessingSecurityScopedResource() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + let value = try? api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.startAccessingSecurityScopedResourceCalled) + XCTAssertEqual(value, instance.startAccessingSecurityScopedResource()) + } + + func testStopAccessingSecurityScopedResource() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + try? api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.stopAccessingSecurityScopedResourceCalled) + } + +} +class TestURL: URL { + var startAccessingSecurityScopedResourceCalled = false + var stopAccessingSecurityScopedResourceCalled = false + + + override func startAccessingSecurityScopedResource() { + startAccessingSecurityScopedResourceCalled = true + } + override func stopAccessingSecurityScopedResource() { + stopAccessingSecurityScopedResourceCalled = true + } } */ -protocol PigeonApiDelegateFileManager { - func defaultManager(pigeonApi: PigeonApiFileManager) throws -> FileManager - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool - func contents(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> FlutterStandardTypedData? +protocol PigeonApiDelegateFileHandle { + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? + func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } -protocol PigeonApiProtocolFileManager { +protocol PigeonApiProtocolFileHandle { } -final class PigeonApiFileManager: PigeonApiProtocolFileManager { +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateFileManager - init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileManager) { + let pigeonDelegate: PigeonApiDelegateFileHandle + init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileManager?) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let defaultManagerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager", binaryMessenger: binaryMessenger, codec: codec) + let forReadingFromUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.forReadingFromUrl", binaryMessenger: binaryMessenger, codec: codec) if let api = api { - defaultManagerChannel.setMessageHandler { message, reply in + forReadingFromUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 + let urlArg = args[1] as! URL do { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(try api.pigeonDelegate.defaultManager(pigeonApi: api), withIdentifier: pigeonIdentifierArg) + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( +try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), +withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) } } } else { - defaultManagerChannel.setMessageHandler(nil) + forReadingFromUrlChannel.setMessageHandler(nil) } - let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileExists", binaryMessenger: binaryMessenger, codec: codec) + let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) if let api = api { - fileExistsChannel.setMessageHandler { message, reply in + readToEndChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String + let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) } } } else { - fileExistsChannel.setMessageHandler(nil) + readToEndChannel.setMessageHandler(nil) } - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile", binaryMessenger: binaryMessenger, codec: codec) + let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) if let api = api { - isReadableFileChannel.setMessageHandler { message, reply in + closeChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String + let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isReadableFileChannel.setMessageHandler(nil) - } - let contentsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.contents", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - contentsChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String - do { - let result = try api.pigeonDelegate.contents(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) - reply(wrapResult(result)) + try api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) } catch { reply(wrapError(error)) } } } else { - contentsChannel.setMessageHandler(nil) + closeChannel.setMessageHandler(nil) } } - ///Creates a Dart instance of FileManager and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileManager, completion: @escaping (Result) -> Void) { + ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -758,7 +795,7 @@ final class PigeonApiFileManager: PigeonApiProtocolFileManager { let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance" + let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance" let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { @@ -787,25 +824,21 @@ import Foundation -/// ProxyApi implementation for `FileManager`. +/// ProxyApi implementation for `FileHandle`. /// /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. -class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { - func defaultManager(pigeonApi: PigeonApiFileManager): FileManager { - return FileManager.defaultManager - } - - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { - return pigeonInstance.fileExists(atPath: atPath) +class FileHandleProxyAPIDelegate : PigeonApiDelegateFileHandle { + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle { + return FileHandle(,url: url) } - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { - return pigeonInstance.isReadableFile(atPath: atPath) + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? { + return pigeonInstance.readToEnd() } - func contents(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> FlutterStandardTypedData? { - return pigeonInstance.contents(atPath: atPath) + func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { + pigeonInstance.close() } } @@ -822,61 +855,47 @@ import XCTest @testable import cross_file_ios -class FileManagerTests: XCTestCase { - func testFileExists() { +class FileHandleTests: XCTestCase { + func testForReadingFromUrl() { let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: instance, atPath: atPath) - - XCTAssertEqual(instance.fileExistsArgs, [atPath]) - XCTAssertEqual(value, instance.fileExists(atPath: atPath)) + let instance = try? api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: TestURL) + XCTAssertNotNil(instance) } - func testIsReadableFile() { + func testReadToEnd() { let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + let instance = TestFileHandle() + let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance ) - XCTAssertEqual(instance.isReadableFileArgs, [atPath]) - XCTAssertEqual(value, instance.isReadableFile(atPath: atPath)) + XCTAssertTrue(instance.readToEndCalled) + XCTAssertEqual(value, instance.readToEnd()) } - func testContents() { + func testClose() { let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.contents(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + let instance = TestFileHandle() + try? api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: instance ) - XCTAssertEqual(instance.contentsArgs, [atPath]) - XCTAssertEqual(value, instance.contents(atPath: atPath)) + XCTAssertTrue(instance.closeCalled) } } -class TestFileManager: FileManager { - var fileExistsArgs: [AnyHashable?]? = nil - var isReadableFileArgs: [AnyHashable?]? = nil - var contentsArgs: [AnyHashable?]? = nil +class TestFileHandle: FileHandle { + var readToEndCalled = false + var closeCalled = false - override func fileExists() { - fileExistsArgs = [atPath] - return true - } - override func isReadableFile() { - isReadableFileArgs = [atPath] - return true + override func readToEnd() { + readToEndCalled = true } - override func contents() { - contentsArgs = [atPath] - return byteArrayOf(0xA1.toByte()) + override func close() { + closeCalled = true } } */ diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift similarity index 65% rename from packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift rename to packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift index 385db6915d61..b897ab3260df 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/UrlProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift @@ -9,12 +9,16 @@ import Foundation /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. class URLProxyAPIDelegate : PigeonApiDelegateURL { - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws -> Bool { - return URL(string: url)!.startAccessingSecurityScopedResource() + func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? { + return URL(fileURLWithPath: path) } - - func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, url: String) throws { - URL(string: url)!.stopAccessingSecurityScopedResource() + + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool { + pigeonInstance.startAccessingSecurityScopedResource() + } + + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws { + pigeonInstance.stopAccessingSecurityScopedResource() } } diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart index 6000f7421785..d833bb69252e 100644 --- a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart +++ b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart @@ -1,4 +1,4 @@ export 'src/ios_cross_file.dart'; export 'src/cross_file_ios.dart'; export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show PlatformXFileCreationParams; + show PlatformSharedStorageXFileCreationParams; diff --git a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart index f79429dfe51d..881b156c43bd 100644 --- a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart +++ b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart @@ -10,6 +10,15 @@ final class CrossFileIOS extends CrossFilePlatform { @override IOSXFile createPlatformXFile(PlatformXFileCreationParams params) { + return IOSXFile( + PlatformSharedStorageXFileCreationParams(path: params.path), + ); + } + + @override + PlatformSharedStorageXFile createPlatformSharedStorageXFile( + PlatformSharedStorageXFileCreationParams params, + ) { return IOSXFile(params); } } diff --git a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart index c38544e82f54..f01b818834e6 100644 --- a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart +++ b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart @@ -38,21 +38,16 @@ List wrapResponse({Object? result, PlatformException? error, bool empty /// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. @visibleForTesting class PigeonOverrides { - /// Overrides [FileManager.defaultManager]. - static FileManager? fileManager_defaultManager; + /// Overrides [FileHandle.forReadingFromUrl]. + static FileHandle Function({required URL url})? fileHandle_forReadingFromUrl; - /// Overrides [URL.startAccessingSecurityScopedResource]. - static Future Function(String)? - uRL_startAccessingSecurityScopedResource; - - /// Overrides [URL.stopAccessingSecurityScopedResource]. - static Future Function(String)? uRL_stopAccessingSecurityScopedResource; + /// Overrides [URL.fileURLWithPath]. + static Future Function(String)? uRL_fileURLWithPath; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { - uRL_startAccessingSecurityScopedResource = null; - uRL_stopAccessingSecurityScopedResource = null; - fileManager_defaultManager = null; + uRL_fileURLWithPath = null; + fileHandle_forReadingFromUrl = null; } } @@ -163,7 +158,7 @@ class PigeonInstanceManager { ); _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); URL.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - FileManager.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -507,18 +502,47 @@ class URL extends PigeonInternalProxyApiBaseClass { } } - static Future startAccessingSecurityScopedResource( - String url, { + static Future fileURLWithPath( + String path, { BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) async { - if (PigeonOverrides.uRL_startAccessingSecurityScopedResource != null) { - return PigeonOverrides.uRL_startAccessingSecurityScopedResource!(url); + if (PigeonOverrides.uRL_fileURLWithPath != null) { + return PigeonOverrides.uRL_fileURLWithPath!(path); } final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.URL.fileURLWithPath'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([path]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as URL?); + } + } + + Future startAccessingSecurityScopedResource() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecURL; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource'; final BasicMessageChannel pigeonVar_channel = @@ -528,7 +552,7 @@ class URL extends PigeonInternalProxyApiBaseClass { binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = - pigeonVar_channel.send([url]); + pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -549,17 +573,9 @@ class URL extends PigeonInternalProxyApiBaseClass { } } - static Future stopAccessingSecurityScopedResource( - String url, { - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) async { - if (PigeonOverrides.uRL_stopAccessingSecurityScopedResource != null) { - return PigeonOverrides.uRL_stopAccessingSecurityScopedResource!(url); - } + Future stopAccessingSecurityScopedResource() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + _pigeonVar_codecURL; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource'; @@ -570,7 +586,7 @@ class URL extends PigeonInternalProxyApiBaseClass { binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = - pigeonVar_channel.send([url]); + pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -595,57 +611,104 @@ class URL extends PigeonInternalProxyApiBaseClass { } } -class FileManager extends PigeonInternalProxyApiBaseClass { - /// Constructs [FileManager] without creating the associated native object. +class FileHandle extends PigeonInternalProxyApiBaseClass { + factory FileHandle.forReadingFromUrl({ + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + required URL url, + }) { + if (PigeonOverrides.fileHandle_forReadingFromUrl != null) { + return PigeonOverrides.fileHandle_forReadingFromUrl!(url: url); + } + return FileHandle.pigeon_forReadingFromUrl( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + url: url, + ); + } + + @protected + FileHandle.pigeon_forReadingFromUrl({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required URL url, + }) { + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileHandle.forReadingFromUrl'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier, url]); + () async { + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + } + + /// Constructs [FileHandle] without creating the associated native object. /// /// This should only be used by subclasses created by this library or to /// create copies for an [PigeonInstanceManager]. @protected - FileManager.pigeon_detached({ + FileHandle.pigeon_detached({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, }); - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileManager = + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileHandle = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - static final FileManager _defaultManager = pigeonVar_defaultManager(); - - static FileManager get defaultManager => - PigeonOverrides.fileManager_defaultManager ?? _defaultManager; - static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - FileManager Function()? pigeon_newInstance, + FileHandle Function()? pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null.'); + 'Argument for dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null, expected non-null int.'); + 'Argument for dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( pigeon_newInstance?.call() ?? - FileManager.pigeon_detached( + FileHandle.pigeon_detached( pigeon_binaryMessenger: pigeon_binaryMessenger, pigeon_instanceManager: pigeon_instanceManager, ), @@ -663,48 +726,12 @@ class FileManager extends PigeonInternalProxyApiBaseClass { } } - static FileManager pigeonVar_defaultManager() { - final FileManager pigeonVar_instance = FileManager.pigeon_detached(); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); - final BinaryMessenger pigeonVar_binaryMessenger = - ServicesBinding.instance.defaultBinaryMessenger; - final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance - .addDartCreatedInstance(pigeonVar_instance); - () async { - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - }(); - return pigeonVar_instance; - } - - Future fileExists(String atPath) async { + Future readToEnd() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; + _pigeonVar_codecFileHandle; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.fileExists'; + 'dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, @@ -712,7 +739,7 @@ class FileManager extends PigeonInternalProxyApiBaseClass { binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); + pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -723,56 +750,17 @@ class FileManager extends PigeonInternalProxyApiBaseClass { message: pigeonVar_replyList[1] as String?, details: pigeonVar_replyList[2], ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future isReadableFile(String atPath) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; + return (pigeonVar_replyList[0] as Uint8List?); } } - Future contents(String atPath) async { + Future close() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; + _pigeonVar_codecFileHandle; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.contents'; + 'dev.flutter.pigeon.cross_file_ios.FileHandle.close'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, @@ -780,7 +768,7 @@ class FileManager extends PigeonInternalProxyApiBaseClass { binaryMessenger: pigeonVar_binaryMessenger, ); final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); + pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -792,13 +780,13 @@ class FileManager extends PigeonInternalProxyApiBaseClass { details: pigeonVar_replyList[2], ); } else { - return (pigeonVar_replyList[0] as Uint8List?); + return; } } @override - FileManager pigeon_copy() { - return FileManager.pigeon_detached( + FileHandle pigeon_copy() { + return FileHandle.pigeon_detached( pigeon_binaryMessenger: pigeon_binaryMessenger, pigeon_instanceManager: pigeon_instanceManager, ); diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index b65a2225a709..9eb0102205fc 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -7,17 +7,22 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart base class IOSXFile extends PlatformSharedStorageXFile { IOSXFile(super.params) : super.implementation(); - final FileManager _fileManager = FileManager.defaultManager; - @override - Future canRead() { - // TODO: implement canRead - throw UnimplementedError(); + Future canRead() async { + final URL? url = await URL.fileURLWithPath(params.path); + + if (url case URL url) { + final bool canRead = await url.startAccessingSecurityScopedResource(); + await url.stopAccessingSecurityScopedResource(); + return canRead; + } + + return false; } @override Future exists() { - return _fileManager.fileExists(params.path); + return canRead(); } @override @@ -46,22 +51,30 @@ base class IOSXFile extends PlatformSharedStorageXFile { @override Future readAsBytes() async { - final bool canRead = await URL.startAccessingSecurityScopedResource(params.path); - if (canRead) { - final Uint8List? bytes = await _fileManager.contents(params.path); - URL.stopAccessingSecurityScopedResource(params.path); + final URL? url = await URL.fileURLWithPath(params.path); + + if (url case URL url) { + final bool canRead = await url.startAccessingSecurityScopedResource(); + if (canRead) { + final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); + try { + final Uint8List? bytes = await fileHandle.readToEnd(); + await url.stopAccessingSecurityScopedResource(); - if (bytes case Uint8List bytes) { - return bytes; + if (bytes case Uint8List bytes) { + return bytes; + } + } finally { + fileHandle.close(); + } } } - throw UnsupportedError('Can access bytes to file: ${params.path}'); + throw UnsupportedError('Cant access bytes to file: ${params.path}'); } @override - Future readAsString({Encoding encoding = utf8}) { - // TODO: implement readAsString - throw UnimplementedError(); + Future readAsString({Encoding encoding = utf8}) async { + return encoding.decode(await readAsBytes()); } } diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart index 39299c82865b..c5f8df75f894 100644 --- a/packages/cross_file/cross_file_ios/pigeons/foundation.dart +++ b/packages/cross_file/cross_file_ios/pigeons/foundation.dart @@ -11,20 +11,18 @@ import 'package:pigeon/pigeon.dart'; @ProxyApi() abstract class URL { @static - bool startAccessingSecurityScopedResource(String url); + URL? fileURLWithPath(String path); - @static - void stopAccessingSecurityScopedResource(String url); + bool startAccessingSecurityScopedResource(); + + void stopAccessingSecurityScopedResource(); } @ProxyApi() -abstract class FileManager { - @static - late final FileManager defaultManager; +abstract class FileHandle { + FileHandle.forReadingFromUrl(URL url); - bool fileExists(String atPath); + Uint8List? readToEnd(); - bool isReadableFile(String atPath); - - Uint8List? contents(String atPath); -} \ No newline at end of file + void close(); +} diff --git a/packages/cross_file/cross_file_ios/pubspec.yaml b/packages/cross_file/cross_file_ios/pubspec.yaml index bedb0db2f23f..e2d5511771b1 100644 --- a/packages/cross_file/cross_file_ios/pubspec.yaml +++ b/packages/cross_file/cross_file_ios/pubspec.yaml @@ -20,12 +20,12 @@ dependencies: sdk: flutter cross_file_platform_interface: path: ../cross_file_platform_interface + +dev_dependencies: + flutter_test: + sdk: flutter pigeon: git: url: git@github.com:bparrishMines/packages.git ref: pigeon_helper path: packages/pigeon - -dev_dependencies: - flutter_test: - sdk: flutter diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart index bcf267632bfd..f63cb6f20c64 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart @@ -2,6 +2,9 @@ import 'package:flutter/foundation.dart'; import '../../cross_file_platform_interface.dart'; +// TODO: difference between path and tostring +// TODO: Absolute string definition: "Returns true if this URI is absolute, i.e. if it contains an explicit scheme." +// TODO: it is relative if not @immutable base class PlatformSharedStorageXFileCreationParams extends PlatformXFileCreationParams { @@ -28,8 +31,8 @@ abstract base class PlatformSharedStorageXFile extends PlatformXFile { } @protected - PlatformSharedStorageXFile.implementation(super.params) - : super.implementation(); + PlatformSharedStorageXFile.implementation(PlatformSharedStorageXFileCreationParams params) + : super.implementation(params); @override PlatformSharedStorageXFileCreationParams get params => @@ -40,4 +43,8 @@ abstract base class PlatformSharedStorageXFile extends PlatformXFile { super.extension as SharedStoragePlatformXFileExtension?; Future delete(); + + Future absoluteString() { + throw UnimplementedError(); + } } diff --git a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj index 3a0c60083fa5..67839eeb7bf4 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -180,6 +180,7 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + C04A430C6B9C2A1A0197124B /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -351,6 +352,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + C04A430C6B9C2A1A0197124B /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -586,6 +604,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 7607cff6ce75..88f2c790671c 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -44,6 +44,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> ['txt', 'json'], - uniformTypeIdentifiers: ['public.text'], + //uniformTypeIdentifiers: ['somefile.txt'], ); - final XFile? file = await FileSelectorPlatform.instance.openFile( - acceptedTypeGroups: [typeGroup], + final IOSXFile? file = await FileSelectorIOS().openFile2( + //acceptedTypeGroups: [typeGroup], ); if (file == null) { // Operation was canceled by the user. return; } - final String fileName = file.name; - final String fileContent = await file.readAsString(); + //final String fileName = file.name; + print(file.params.path); + print(await file.canRead()); + print(await file.exists()); + print(await file.readAsBytes()); + final String fileContent = 'hello'; // = await file.readAsString(); if (context.mounted) { await showDialog( context: context, - builder: (BuildContext context) => TextDisplay(fileName, fileContent), + builder: (BuildContext context) => TextDisplay('FileName', fileContent), ); } } diff --git a/packages/file_selector/file_selector_ios/example/pubspec.yaml b/packages/file_selector/file_selector_ios/example/pubspec.yaml index 68c190da3fdd..7fab02985419 100644 --- a/packages/file_selector/file_selector_ios/example/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/example/pubspec.yaml @@ -8,6 +8,8 @@ environment: flutter: ">=3.35.0" dependencies: + cross_file_ios: + path: ../../../cross_file/cross_file_ios # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 diff --git a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift index e7d6f1703799..4eed37bfd201 100644 --- a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift +++ b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift @@ -75,5 +75,26 @@ public class FileSelectorPlugin: NSObject, FlutterPlugin, FileSelectorApi { ) } } + + func openFile2(config: FileSelectorConfig, completion: @escaping (Result<[String], any Error>) -> Void) { + let completionBridge = PickerCompletionBridge(completion: completion, owner: self) + let documentPicker = + documentPickerViewControllerOverride + ?? UIDocumentPickerViewController( + documentTypes: config.utis, + in: .open) + documentPicker.allowsMultipleSelection = config.allowMultiSelection + documentPicker.delegate = completionBridge + let presenter = + self.viewPresenterOverride ?? UIApplication.shared.delegate?.window??.rootViewController + if let presenter = presenter { + pendingCompletions.insert(completionBridge) + presenter.present(documentPicker, animated: true, completion: nil) + } else { + completion( + .failure(PigeonError(code: "error", message: "Missing root view controller.", details: nil)) + ) + } + } } diff --git a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift index 36f897df2e85..d64251254720 100644 --- a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift +++ b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift @@ -110,12 +110,12 @@ func deepEqualsmessages(_ lhs: Any?, _ rhs: Any?) -> Bool { func deepHashmessages(value: Any?, hasher: inout Hasher) { if let valueList = value as? [AnyHashable] { - for item in valueList { deepHashmessages(value: item, hasher: &hasher) } - return + for item in valueList { deepHashmessages(value: item, hasher: &hasher) } + return } if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { + for key in valueDict.keys { hasher.combine(key) deepHashmessages(value: valueDict[key]!, hasher: &hasher) } @@ -129,11 +129,14 @@ func deepHashmessages(value: Any?, hasher: inout Hasher) { return hasher.combine(String(describing: value)) } + + /// Generated class from Pigeon that represents data sent in messages. struct FileSelectorConfig: Hashable { var utis: [String] var allowMultiSelection: Bool + // swift-format-ignore: AlwaysUseLowerCamelCase static func fromList(_ pigeonVar_list: [Any?]) -> FileSelectorConfig? { let utis = pigeonVar_list[0] as! [String] @@ -151,8 +154,7 @@ struct FileSelectorConfig: Hashable { ] } static func == (lhs: FileSelectorConfig, rhs: FileSelectorConfig) -> Bool { - return deepEqualsmessages(lhs.toList(), rhs.toList()) - } + return deepEqualsmessages(lhs.toList(), rhs.toList()) } func hash(into hasher: inout Hasher) { deepHashmessages(value: toList(), hasher: &hasher) } @@ -194,23 +196,20 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter()) } + /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FileSelectorApi { func openFile(config: FileSelectorConfig, completion: @escaping (Result<[String], Error>) -> Void) + func openFile2(config: FileSelectorConfig, completion: @escaping (Result<[String], Error>) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class FileSelectorApiSetup { static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared } /// Sets up an instance of `FileSelectorApi` to handle messages through the `binaryMessenger`. - static func setUp( - binaryMessenger: FlutterBinaryMessenger, api: FileSelectorApi?, - messageChannelSuffix: String = "" - ) { + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FileSelectorApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let openFileChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let openFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { openFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -227,5 +226,22 @@ class FileSelectorApiSetup { } else { openFileChannel.setMessageHandler(nil) } + let openFile2Channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile2\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + openFile2Channel.setMessageHandler { message, reply in + let args = message as! [Any?] + let configArg = args[0] as! FileSelectorConfig + api.openFile2(config: configArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + openFile2Channel.setMessageHandler(nil) + } } } diff --git a/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart b/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart index ac2af48c7bc4..aaa740ff7bde 100644 --- a/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart +++ b/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cross_file_ios/cross_file_ios.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:flutter/foundation.dart' show visibleForTesting; @@ -34,6 +35,21 @@ class FileSelectorIOS extends FileSelectorPlatform { return path.isEmpty ? null : XFile(path.first); } + Future openFile2({ + List? acceptedTypeGroups, + String? initialDirectory, + String? confirmButtonText, + }) async { + final List paths = await _hostApi.openFile2( + FileSelectorConfig( + utis: _allowedUtiListFromTypeGroups(acceptedTypeGroups), + ), + ); + return paths.isEmpty + ? null + : IOSXFile(PlatformSharedStorageXFileCreationParams(path: paths.first)); + } + @override Future> openFiles({ List? acceptedTypeGroups, diff --git a/packages/file_selector/file_selector_ios/lib/src/messages.g.dart b/packages/file_selector/file_selector_ios/lib/src/messages.g.dart index 5ecb21446ba1..6c231c0b766c 100644 --- a/packages/file_selector/file_selector_ios/lib/src/messages.g.dart +++ b/packages/file_selector/file_selector_ios/lib/src/messages.g.dart @@ -17,39 +17,21 @@ PlatformException _createConnectionError(String channelName) { message: 'Unable to establish connection on channel: "$channelName".', ); } - -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; - } - return [error.code, error.message, error.details]; -} - bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed.every( - ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), - ); + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every( - (MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key]), - ); + return a.length == b.length && a.entries.every((MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key])); } return a == b; } + class FileSelectorConfig { FileSelectorConfig({ this.utis = const [], @@ -61,12 +43,14 @@ class FileSelectorConfig { bool allowMultiSelection; List _toList() { - return [utis, allowMultiSelection]; + return [ + utis, + allowMultiSelection, + ]; } Object encode() { - return _toList(); - } + return _toList(); } static FileSelectorConfig decode(Object result) { result as List; @@ -90,9 +74,11 @@ class FileSelectorConfig { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => Object.hashAll(_toList()) +; } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -100,7 +86,7 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileSelectorConfig) { + } else if (value is FileSelectorConfig) { buffer.putUint8(129); writeValue(buffer, value.encode()); } else { @@ -111,7 +97,7 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: return FileSelectorConfig.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -123,13 +109,9 @@ class FileSelectorApi { /// Constructor for [FileSelectorApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - FileSelectorApi({ - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty - ? '.$messageChannelSuffix' - : ''; + FileSelectorApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -137,17 +119,41 @@ class FileSelectorApi { final String pigeonVar_messageChannelSuffix; Future> openFile(FileSelectorConfig config) async { - final String pigeonVar_channelName = - 'dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [config], + final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([config]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } + + Future> openFile2(FileSelectorConfig config) async { + final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile2$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([config]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { diff --git a/packages/file_selector/file_selector_ios/pigeons/messages.dart b/packages/file_selector/file_selector_ios/pigeons/messages.dart index 857e888c2846..6e6259a41ca0 100644 --- a/packages/file_selector/file_selector_ios/pigeons/messages.dart +++ b/packages/file_selector/file_selector_ios/pigeons/messages.dart @@ -26,4 +26,7 @@ abstract class FileSelectorApi { @async @ObjCSelector('openFileSelectorWithConfig:') List openFile(FileSelectorConfig config); + + @async + List openFile2(FileSelectorConfig config); } diff --git a/packages/file_selector/file_selector_ios/pubspec.yaml b/packages/file_selector/file_selector_ios/pubspec.yaml index 42a3c85ae78e..0743b0d96a30 100644 --- a/packages/file_selector/file_selector_ios/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/pubspec.yaml @@ -17,6 +17,8 @@ flutter: pluginClass: FileSelectorPlugin dependencies: + cross_file_ios: + path: ../../cross_file/cross_file_ios file_selector_platform_interface: ^2.3.0 flutter: sdk: flutter From 76adb9d1677bd8669e74d4e2c5de6d28c6f88216 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sun, 16 Nov 2025 14:34:05 -0600 Subject: [PATCH 019/398] ios can read --- .../cross_file/cross_file_ios/lib/src/ios_cross_file.dart | 4 ++-- .../file_selector_ios/example/lib/open_text_page.dart | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index 9eb0102205fc..999e33f7bc6d 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -59,13 +59,13 @@ base class IOSXFile extends PlatformSharedStorageXFile { final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); try { final Uint8List? bytes = await fileHandle.readToEnd(); - await url.stopAccessingSecurityScopedResource(); if (bytes case Uint8List bytes) { return bytes; } } finally { - fileHandle.close(); + await url.stopAccessingSecurityScopedResource(); + await fileHandle.close(); } } } diff --git a/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart b/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart index b5974d0393de..7439ddc58a3a 100644 --- a/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart +++ b/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart @@ -28,10 +28,9 @@ class OpenTextPage extends StatelessWidget { } //final String fileName = file.name; print(file.params.path); - print(await file.canRead()); - print(await file.exists()); - print(await file.readAsBytes()); - final String fileContent = 'hello'; // = await file.readAsString(); + //print(await file.canRead()); + //print(await file.exists()); + final String fileContent = await file.readAsString(); if (context.mounted) { await showDialog( From ebdf3d9ff3c00c7c9bb316c9e92c0586ac406a73 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 18 Nov 2025 10:02:28 -0500 Subject: [PATCH 020/398] some workign code on ios impl --- ...RLResolvingBookmarkDataResponseTests.swift | 32 +++ .../example/ios/RunnerTests/UrlTests.swift | 19 ++ .../ios/Classes/ProxyAPIDelegate.swift | 4 + .../URLResolvingBookmarkDataResponse.swift | 10 + .../ios/Classes/proxies/Foundation.g.swift | 244 +++++++++++++++++- .../Classes/proxies/URLProxyAPIDelegate.swift | 22 +- ...BookmarkDataResponseProxyAPIDelegate.swift | 20 ++ .../cross_file_ios/lib/src/foundation.g.dart | 216 ++++++++++++++++ .../lib/src/ios_cross_file.dart | 56 ++-- .../cross_file_ios/pigeons/foundation.dart | 24 ++ .../example/lib/open_text_page.dart | 4 +- 11 files changed, 627 insertions(+), 24 deletions(-) create mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift new file mode 100644 index 000000000000..0b3d850baefa --- /dev/null +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class URLResolvingBookmarkDataResponseTests: XCTestCase { + func testUrl() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) + + let instance = TestURLResolvingBookmarkDataResponse() + let value = try? api.pigeonDelegate.url(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, instance.url) + } + + func testIsStale() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) + + let instance = TestURLResolvingBookmarkDataResponse() + let value = try? api.pigeonDelegate.isStale(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, instance.isStale) + } + +} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift index 4a556b3e015c..30c704af2f17 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift @@ -9,6 +9,20 @@ import XCTest @testable import cross_file_ios class URLTests: XCTestCase { + func testBookmarkData() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + let options = [.minimalBookmark] + let keys = [.isDirectoryKey] + let relativeTo = TestURL + let value = try? api.pigeonDelegate.bookmarkData(pigeonApi: api, pigeonInstance: instance, options: options, keys: keys, relativeTo: relativeTo) + + XCTAssertEqual(instance.bookmarkDataArgs, [options, keys, relativeTo]) + XCTAssertEqual(value, instance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo)) + } + func testStartAccessingSecurityScopedResource() { let registrar = TestProxyApiRegistrar() let api = registrar.apiDelegate.pigeonApiURL(registrar) @@ -32,10 +46,15 @@ class URLTests: XCTestCase { } class TestURL: URL { + var bookmarkDataArgs: [AnyHashable?]? = nil var startAccessingSecurityScopedResourceCalled = false var stopAccessingSecurityScopedResourceCalled = false + override func bookmarkData() { + bookmarkDataArgs = [options, keys, relativeTo] + return byteArrayOf(0xA1.toByte()) + } override func startAccessingSecurityScopedResource() { startAccessingSecurityScopedResourceCalled = true } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift index 19d2517d4ccf..0f5a3aaa4408 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift @@ -18,5 +18,9 @@ open class ProxyApiDelegate: FoundationPigeonProxyApiDelegate { func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle { return PigeonApiFileHandle(pigeonRegistrar: registrar, delegate: FileHandleProxyAPIDelegate()) } + + func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURLResolvingBookmarkDataResponse { + return PigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar: registrar, delegate: URLResolvingBookmarkDataResponseProxyAPIDelegate()) + } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift b/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift new file mode 100644 index 000000000000..4c7a0cd3ee70 --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift @@ -0,0 +1,10 @@ +class URLResolvingBookmarkDataResponse { + let url: URL + let isStale: Bool + + init(url: URL, isStale: Bool) { + self.url = url + self.isStale = isStale + } +} + diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift index 5896ec9aa766..1d09de1e3bc8 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift @@ -363,6 +363,9 @@ private class FoundationPigeonInstanceManagerApi { } } protocol FoundationPigeonProxyApiDelegate { + /// An implementation of [PigeonApiURLResolvingBookmarkDataResponse] used to add a new Dart instance of + /// `URLResolvingBookmarkDataResponse` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURLResolvingBookmarkDataResponse /// An implementation of [PigeonApiURL] used to add a new Dart instance of /// `URL` to the Dart `InstanceManager` and make calls to Dart. func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL @@ -455,12 +458,23 @@ private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandard } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String || value is URLBookmarkCreationOptions || value is URLResourceKeyEnum || value is URLBookmarkResolutionOptions { super.writeValue(value) return } + if let instance = value as? URLResolvingBookmarkDataResponse { + pigeonRegistrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + if let instance = value as? URL { pigeonRegistrar.apiDelegate.pigeonApiURL(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance @@ -509,10 +523,63 @@ private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandard } } +enum URLBookmarkCreationOptions: Int { + case minimalBookmark = 0 + case suitableForBookmarkOptions = 1 +} + +enum URLResourceKeyEnum: Int { + case isDirectoryKey = 0 + case parentDirectoryURLKey = 1 +} + +enum URLBookmarkResolutionOptions: Int { + case withoutUI = 0 + case withoutMounting = 1 +} + private class FoundationPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) + if let enumResultAsInt = enumResultAsInt { + return URLBookmarkCreationOptions(rawValue: enumResultAsInt) + } + return nil + case 130: + let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) + if let enumResultAsInt = enumResultAsInt { + return URLResourceKeyEnum(rawValue: enumResultAsInt) + } + return nil + case 131: + let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) + if let enumResultAsInt = enumResultAsInt { + return URLBookmarkResolutionOptions(rawValue: enumResultAsInt) + } + return nil + default: + return super.readValue(ofType: type) + } + } } private class FoundationPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? URLBookmarkCreationOptions { + super.writeByte(129) + super.writeValue(value.rawValue) + } else if let value = value as? URLResourceKeyEnum { + super.writeByte(130) + super.writeValue(value.rawValue) + } else if let value = value as? URLBookmarkResolutionOptions { + super.writeByte(131) + super.writeValue(value.rawValue) + } else { + super.writeValue(value) + } + } } private class FoundationPigeonCodecReaderWriter: FlutterStandardReaderWriter { @@ -529,8 +596,121 @@ class FoundationPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { static let shared = FoundationPigeonCodec(readerWriter: FoundationPigeonCodecReaderWriter()) } +protocol PigeonApiDelegateURLResolvingBookmarkDataResponse { + func url(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> URL + func isStale(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> Bool +} + +protocol PigeonApiProtocolURLResolvingBookmarkDataResponse { +} + +final class PigeonApiURLResolvingBookmarkDataResponse: PigeonApiProtocolURLResolvingBookmarkDataResponse { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateURLResolvingBookmarkDataResponse + init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateURLResolvingBookmarkDataResponse) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + ///Creates a Dart instance of URLResolvingBookmarkDataResponse and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: URLResolvingBookmarkDataResponse, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + let urlArg = try! pigeonDelegate.url(pigeonApi: self, pigeonInstance: pigeonInstance) + let isStaleArg = try! pigeonDelegate.isStale(pigeonApi: self, pigeonInstance: pigeonInstance) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg, urlArg, isStaleArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + } +} + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + + + +/// ProxyApi implementation for `URLResolvingBookmarkDataResponse`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class URLResolvingBookmarkDataResponseProxyAPIDelegate : PigeonApiDelegateURLResolvingBookmarkDataResponse { + func url(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> URL { + return pigeonInstance.url + } + + func isStale(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> Bool { + return pigeonInstance.isStale + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class URLResolvingBookmarkDataResponseTests: XCTestCase { + func testUrl() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) + + let instance = TestURLResolvingBookmarkDataResponse() + let value = try? api.pigeonDelegate.url(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, instance.url) + } + + func testIsStale() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) + + let instance = TestURLResolvingBookmarkDataResponse() + let value = try? api.pigeonDelegate.isStale(pigeonApi: api, pigeonInstance: instance) + + XCTAssertEqual(value, instance.isStale) + } + +} +*/ + protocol PigeonApiDelegateURL { func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? + func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse + func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws } @@ -566,6 +746,41 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { fileURLWithPathChannel.setMessageHandler(nil) } + let resolvingBookmarkDataChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.resolvingBookmarkData", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + resolvingBookmarkDataChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let dataArg = args[0] as! FlutterStandardTypedData + let optionsArg = args[1] as! [URLBookmarkResolutionOptions] + let relativeToArg: URL? = nilOrValue(args[2]) + do { + let result = try api.pigeonDelegate.resolvingBookmarkData(pigeonApi: api, data: dataArg, options: optionsArg, relativeTo: relativeToArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + resolvingBookmarkDataChannel.setMessageHandler(nil) + } + let bookmarkDataChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.bookmarkData", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + bookmarkDataChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! URL + let optionsArg = args[1] as! [URLBookmarkCreationOptions] + let keysArg: [URLResourceKeyEnum]? = nilOrValue(args[2]) + let relativeToArg: URL? = nilOrValue(args[3]) + do { + let result = try api.pigeonDelegate.bookmarkData(pigeonApi: api, pigeonInstance: pigeonInstanceArg, options: optionsArg, keys: keysArg, relativeTo: relativeToArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + bookmarkDataChannel.setMessageHandler(nil) + } let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource", binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in @@ -650,6 +865,14 @@ class URLProxyAPIDelegate : PigeonApiDelegateURL { return URL.fileURLWithPath(path: path) } + func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse { + return URL.resolvingBookmarkData(data: data, options: options, relativeTo: relativeTo) + } + + func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData { + return pigeonInstance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo) + } + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool { return pigeonInstance.startAccessingSecurityScopedResource() } @@ -673,6 +896,20 @@ import XCTest @testable import cross_file_ios class URLTests: XCTestCase { + func testBookmarkData() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + let options = [.minimalBookmark] + let keys = [.isDirectoryKey] + let relativeTo = TestURL + let value = try? api.pigeonDelegate.bookmarkData(pigeonApi: api, pigeonInstance: instance, options: options, keys: keys, relativeTo: relativeTo) + + XCTAssertEqual(instance.bookmarkDataArgs, [options, keys, relativeTo]) + XCTAssertEqual(value, instance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo)) + } + func testStartAccessingSecurityScopedResource() { let registrar = TestProxyApiRegistrar() let api = registrar.apiDelegate.pigeonApiURL(registrar) @@ -696,10 +933,15 @@ class URLTests: XCTestCase { } class TestURL: URL { + var bookmarkDataArgs: [AnyHashable?]? = nil var startAccessingSecurityScopedResourceCalled = false var stopAccessingSecurityScopedResourceCalled = false + override func bookmarkData() { + bookmarkDataArgs = [options, keys, relativeTo] + return byteArrayOf(0xA1.toByte()) + } override func startAccessingSecurityScopedResource() { startAccessingSecurityScopedResourceCalled = true } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift index b897ab3260df..1ce415bc7958 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Flutter import Foundation /// ProxyApi implementation for `URL`. @@ -13,8 +14,27 @@ class URLProxyAPIDelegate : PigeonApiDelegateURL { return URL(fileURLWithPath: path) } + func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse { + var isStale: Bool = true + let url: URL = try URL(resolvingBookmarkData: data.data, bookmarkDataIsStale: &isStale) + let attr = try FileManager.default.attributesOfItem(atPath: url.path) + print(attr[FileAttributeKey.modificationDate] as? Date as Any) + print(FileManager.default.fileExists(atPath: url.path)) + return URLResolvingBookmarkDataResponse(url: url, isStale: isStale) + } + + func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData { + let data = try pigeonInstance.bookmarkData( + options: [], + includingResourceValuesForKeys: nil, + relativeTo: relativeTo + ) + + return FlutterStandardTypedData(bytes: data) + } + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool { - pigeonInstance.startAccessingSecurityScopedResource() + return pigeonInstance.startAccessingSecurityScopedResource() } func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws { diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift new file mode 100644 index 000000000000..b138038c218a --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift @@ -0,0 +1,20 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +/// ProxyApi implementation for `URLResolvingBookmarkDataResponse`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class URLResolvingBookmarkDataResponseProxyAPIDelegate : PigeonApiDelegateURLResolvingBookmarkDataResponse { + func url(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> URL { + return pigeonInstance.url + } + + func isStale(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> Bool { + return pigeonInstance.isStale + } + +} diff --git a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart index f01b818834e6..e114c848e262 100644 --- a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart +++ b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart @@ -44,9 +44,17 @@ class PigeonOverrides { /// Overrides [URL.fileURLWithPath]. static Future Function(String)? uRL_fileURLWithPath; + /// Overrides [URL.resolvingBookmarkData]. + static Future Function( + Uint8List, + List, + URL?, + )? uRL_resolvingBookmarkData; + /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { uRL_fileURLWithPath = null; + uRL_resolvingBookmarkData = null; fileHandle_forReadingFromUrl = null; } } @@ -157,6 +165,7 @@ class PigeonInstanceManager { }, ); _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + URLResolvingBookmarkDataResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); URL.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; @@ -419,6 +428,21 @@ class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { } +enum URLBookmarkCreationOptions { + minimalBookmark, + suitableForBookmarkOptions, +} + +enum URLResourceKeyEnum { + isDirectoryKey, + parentDirectoryURLKey, +} + +enum URLBookmarkResolutionOptions { + withoutUI, + withoutMounting, +} + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -427,6 +451,15 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); + } else if (value is URLBookmarkCreationOptions) { + buffer.putUint8(129); + writeValue(buffer, value.index); + } else if (value is URLResourceKeyEnum) { + buffer.putUint8(130); + writeValue(buffer, value.index); + } else if (value is URLBookmarkResolutionOptions) { + buffer.putUint8(131); + writeValue(buffer, value.index); } else { super.writeValue(buffer, value); } @@ -435,11 +468,108 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { + case 129: + final int? value = readValue(buffer) as int?; + return value == null ? null : URLBookmarkCreationOptions.values[value]; + case 130: + final int? value = readValue(buffer) as int?; + return value == null ? null : URLResourceKeyEnum.values[value]; + case 131: + final int? value = readValue(buffer) as int?; + return value == null ? null : URLBookmarkResolutionOptions.values[value]; default: return super.readValueOfType(type, buffer); } } } +class URLResolvingBookmarkDataResponse extends PigeonInternalProxyApiBaseClass { + /// Constructs [URLResolvingBookmarkDataResponse] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + URLResolvingBookmarkDataResponse.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.url, + required this.isStale, + }); + + final URL url; + + final bool isStale; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + URLResolvingBookmarkDataResponse Function( + URL url, + bool isStale, + )? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null, expected non-null int.'); + final URL? arg_url = (args[1] as URL?); + assert(arg_url != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null, expected non-null URL.'); + final bool? arg_isStale = (args[2] as bool?); + assert(arg_isStale != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null, expected non-null bool.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call(arg_url!, arg_isStale!) ?? + URLResolvingBookmarkDataResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + url: arg_url!, + isStale: arg_isStale!, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + @override + URLResolvingBookmarkDataResponse pigeon_copy() { + return URLResolvingBookmarkDataResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + url: url, + isStale: isStale, + ); + } +} + class URL extends PigeonInternalProxyApiBaseClass { /// Constructs [URL] without creating the associated native object. /// @@ -539,6 +669,92 @@ class URL extends PigeonInternalProxyApiBaseClass { } } + static Future resolvingBookmarkData( + Uint8List data, + List options, + URL? relativeTo, { + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) async { + if (PigeonOverrides.uRL_resolvingBookmarkData != null) { + return PigeonOverrides.uRL_resolvingBookmarkData!( + data, + options, + relativeTo, + ); + } + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.URL.resolvingBookmarkData'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([data, options, relativeTo]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as URLResolvingBookmarkDataResponse?)!; + } + } + + Future bookmarkData( + List options, + List? keys, + URL? relativeTo, + ) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecURL; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.URL.bookmarkData'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, options, keys, relativeTo]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as Uint8List?)!; + } + } + Future startAccessingSecurityScopedResource() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecURL; diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index 999e33f7bc6d..a1563b452c6d 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'dart:io'; import 'dart:typed_data'; import 'package:cross_file_ios/src/foundation.g.dart'; @@ -7,17 +8,38 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart base class IOSXFile extends PlatformSharedStorageXFile { IOSXFile(super.params) : super.implementation(); - @override - Future canRead() async { - final URL? url = await URL.fileURLWithPath(params.path); + late final Future _originalUrl = URL.fileURLWithPath(params.path); + late final Future _bookmarkUrl = () async { + final URL? url = await _originalUrl; if (url case URL url) { final bool canRead = await url.startAccessingSecurityScopedResource(); - await url.stopAccessingSecurityScopedResource(); - return canRead; + if (canRead) { + try { + final Uint8List? bookmarkData = await url.bookmarkData([], [], null); + if (bookmarkData case Uint8List bookmarkData) { + final URLResolvingBookmarkDataResponse response = await URL + .resolvingBookmarkData(bookmarkData, [], null); + if (response.isStale) { + // TODO: create new bookmark + print('STALE'); + return null; + } + return response.url; + } + } finally { + await url.stopAccessingSecurityScopedResource(); + } + } } - return false; + return null; + }(); + + @override + Future canRead() async { + final URL? bookmarkUrl = await _bookmarkUrl; + return bookmarkUrl != null; } @override @@ -51,22 +73,16 @@ base class IOSXFile extends PlatformSharedStorageXFile { @override Future readAsBytes() async { - final URL? url = await URL.fileURLWithPath(params.path); - - if (url case URL url) { - final bool canRead = await url.startAccessingSecurityScopedResource(); - if (canRead) { - final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); - try { - final Uint8List? bytes = await fileHandle.readToEnd(); + if (await _bookmarkUrl case URL url) { + final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); + try { + final Uint8List? bytes = await fileHandle.readToEnd(); - if (bytes case Uint8List bytes) { - return bytes; - } - } finally { - await url.stopAccessingSecurityScopedResource(); - await fileHandle.close(); + if (bytes case Uint8List bytes) { + return bytes; } + } finally { + await fileHandle.close(); } } diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart index c5f8df75f894..38c1813b23c1 100644 --- a/packages/cross_file/cross_file_ios/pigeons/foundation.dart +++ b/packages/cross_file/cross_file_ios/pigeons/foundation.dart @@ -7,12 +7,36 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) +enum URLBookmarkCreationOptions { minimalBookmark, suitableForBookmarkOptions } + +enum URLResourceKeyEnum { isDirectoryKey, parentDirectoryURLKey } + +enum URLBookmarkResolutionOptions { withoutUI, withoutMounting } + +@ProxyApi() +abstract class URLResolvingBookmarkDataResponse { + late final URL url; + late final bool isStale; +} @ProxyApi() abstract class URL { @static URL? fileURLWithPath(String path); + @static + URLResolvingBookmarkDataResponse resolvingBookmarkData( + Uint8List data, + List options, + URL? relativeTo, + ); + + Uint8List bookmarkData( + List options, + List? keys, + URL? relativeTo, + ); + bool startAccessingSecurityScopedResource(); void stopAccessingSecurityScopedResource(); diff --git a/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart b/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart index 7439ddc58a3a..c9662087f080 100644 --- a/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart +++ b/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart @@ -28,8 +28,8 @@ class OpenTextPage extends StatelessWidget { } //final String fileName = file.name; print(file.params.path); - //print(await file.canRead()); - //print(await file.exists()); + print(await file.canRead()); + print(await file.exists()); final String fileContent = await file.readAsString(); if (context.mounted) { From a1dba7291e9a287759ad353f5e466858befb05d8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:00:21 -0500 Subject: [PATCH 021/398] add filemanager back to handle stuff --- .../example/ios/RunnerTests/UrlTests.swift | 15 + .../ios/Classes/ProxyAPIDelegate.swift | 4 + .../proxies/FileManagerProxyAPIDelegate.swift | 38 +++ .../ios/Classes/proxies/Foundation.g.swift | 314 ++++++++++++++++++ .../Classes/proxies/URLProxyAPIDelegate.swift | 7 +- .../cross_file_ios/lib/src/foundation.g.dart | 278 ++++++++++++++++ .../lib/src/ios_cross_file.dart | 48 ++- .../cross_file_ios/pigeons/foundation.dart | 16 + .../example/lib/open_text_page.dart | 2 + 9 files changed, 708 insertions(+), 14 deletions(-) create mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift index 30c704af2f17..333a0e59a293 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift @@ -9,6 +9,17 @@ import XCTest @testable import cross_file_ios class URLTests: XCTestCase { + func testPath() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + let value = try? api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.pathCalled) + XCTAssertEqual(value, instance.path()) + } + func testBookmarkData() { let registrar = TestProxyApiRegistrar() let api = registrar.apiDelegate.pigeonApiURL(registrar) @@ -46,11 +57,15 @@ class URLTests: XCTestCase { } class TestURL: URL { + var pathCalled = false var bookmarkDataArgs: [AnyHashable?]? = nil var startAccessingSecurityScopedResourceCalled = false var stopAccessingSecurityScopedResourceCalled = false + override func path() { + pathCalled = true + } override func bookmarkData() { bookmarkDataArgs = [options, keys, relativeTo] return byteArrayOf(0xA1.toByte()) diff --git a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift index 0f5a3aaa4408..e323b97de616 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift @@ -22,5 +22,9 @@ open class ProxyApiDelegate: FoundationPigeonProxyApiDelegate { func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURLResolvingBookmarkDataResponse { return PigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar: registrar, delegate: URLResolvingBookmarkDataResponseProxyAPIDelegate()) } + + func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager { + return PigeonApiFileManager(pigeonRegistrar: registrar, delegate: FileManagerProxyAPIDelegate()) + } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift new file mode 100644 index 000000000000..b35d1229aa30 --- /dev/null +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +/// ProxyApi implementation for `FileManager`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { + func defaultManager(pigeonApi: PigeonApiFileManager) -> FileManager { + return FileManager.default + } + + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.fileExists(atPath: atPath) + } + + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.isReadableFile(atPath: atPath) + } + + func fileModificationDate(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { + let attributes: NSDictionary = try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary + if let date = attributes.fileModificationDate() { + return Int64(date.timeIntervalSince1970 * 1000) + } + + return nil + } + + func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { + let attributes: NSDictionary = try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary + return Int64(attributes.fileSize()) + } + +} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift index 1d09de1e3bc8..e97b294822a5 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift @@ -372,6 +372,9 @@ protocol FoundationPigeonProxyApiDelegate { /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle + /// An implementation of [PigeonApiFileManager] used to add a new Dart instance of + /// `FileManager` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager } open class FoundationPigeonProxyApiRegistrar { @@ -415,11 +418,13 @@ open class FoundationPigeonProxyApiRegistrar { FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiURL(self)) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileManager(self)) } func tearDown() { FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { @@ -497,6 +502,17 @@ private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandard } + if let instance = value as? FileManager { + pigeonRegistrar.apiDelegate.pigeonApiFileManager(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) @@ -710,6 +726,7 @@ class URLResolvingBookmarkDataResponseTests: XCTestCase { protocol PigeonApiDelegateURL { func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse + func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws @@ -763,6 +780,21 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { resolvingBookmarkDataChannel.setMessageHandler(nil) } + let pathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.path", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + pathChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! URL + do { + let result = try api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + pathChannel.setMessageHandler(nil) + } let bookmarkDataChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.bookmarkData", binaryMessenger: binaryMessenger, codec: codec) if let api = api { bookmarkDataChannel.setMessageHandler { message, reply in @@ -869,6 +901,10 @@ class URLProxyAPIDelegate : PigeonApiDelegateURL { return URL.resolvingBookmarkData(data: data, options: options, relativeTo: relativeTo) } + func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String { + return pigeonInstance.path() + } + func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData { return pigeonInstance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo) } @@ -896,6 +932,17 @@ import XCTest @testable import cross_file_ios class URLTests: XCTestCase { + func testPath() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiURL(registrar) + + let instance = TestURL() + let value = try? api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: instance ) + + XCTAssertTrue(instance.pathCalled) + XCTAssertEqual(value, instance.path()) + } + func testBookmarkData() { let registrar = TestProxyApiRegistrar() let api = registrar.apiDelegate.pigeonApiURL(registrar) @@ -933,11 +980,15 @@ class URLTests: XCTestCase { } class TestURL: URL { + var pathCalled = false var bookmarkDataArgs: [AnyHashable?]? = nil var startAccessingSecurityScopedResourceCalled = false var stopAccessingSecurityScopedResourceCalled = false + override func path() { + pathCalled = true + } override func bookmarkData() { bookmarkDataArgs = [options, keys, relativeTo] return byteArrayOf(0xA1.toByte()) @@ -1142,3 +1193,266 @@ class TestFileHandle: FileHandle { } */ +protocol PigeonApiDelegateFileManager { + func defaultManager(pigeonApi: PigeonApiFileManager) throws -> FileManager + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool + func fileModificationDate(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? + func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? +} + +protocol PigeonApiProtocolFileManager { +} + +final class PigeonApiFileManager: PigeonApiProtocolFileManager { + unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateFileManager + init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileManager) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileManager?) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let defaultManagerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + defaultManagerChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] as! Int64 + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(try api.pigeonDelegate.defaultManager(pigeonApi: api), withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + defaultManagerChannel.setMessageHandler(nil) + } + let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileExists", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileExistsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileExistsChannel.setMessageHandler(nil) + } + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isReadableFileChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isReadableFileChannel.setMessageHandler(nil) + } + let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileModificationDate", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileModificationDateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.fileModificationDate(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileModificationDateChannel.setMessageHandler(nil) + } + let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileSize", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileSizeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileManager + let atPathArg = args[1] as! String + do { + let result = try api.pigeonDelegate.fileSize(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileSizeChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of FileManager and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: FileManager, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + } +} + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + + + +/// ProxyApi implementation for `FileManager`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { + func defaultManager(pigeonApi: PigeonApiFileManager): FileManager { + return FileManager.defaultManager + } + + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.fileExists(atPath: atPath) + } + + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + return pigeonInstance.isReadableFile(atPath: atPath) + } + + func fileModificationDate(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { + return pigeonInstance.fileModificationDate(atPath: atPath) + } + + func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { + return pigeonInstance.fileSize(atPath: atPath) + } + +} +*/ + +/* +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +import Flutter +import XCTest + +@testable import cross_file_ios + +class FileManagerTests: XCTestCase { + func testFileExists() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.fileExistsArgs, [atPath]) + XCTAssertEqual(value, instance.fileExists(atPath: atPath)) + } + + func testIsReadableFile() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.isReadableFileArgs, [atPath]) + XCTAssertEqual(value, instance.isReadableFile(atPath: atPath)) + } + + func testFileModificationDate() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.fileModificationDate(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.fileModificationDateArgs, [atPath]) + XCTAssertEqual(value, instance.fileModificationDate(atPath: atPath)) + } + + func testFileSize() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileManager(registrar) + + let instance = TestFileManager() + let atPath = "myString" + let value = try? api.pigeonDelegate.fileSize(pigeonApi: api, pigeonInstance: instance, atPath: atPath) + + XCTAssertEqual(instance.fileSizeArgs, [atPath]) + XCTAssertEqual(value, instance.fileSize(atPath: atPath)) + } + +} +class TestFileManager: FileManager { + var fileExistsArgs: [AnyHashable?]? = nil + var isReadableFileArgs: [AnyHashable?]? = nil + var fileModificationDateArgs: [AnyHashable?]? = nil + var fileSizeArgs: [AnyHashable?]? = nil + + + override func fileExists() { + fileExistsArgs = [atPath] + return true + } + override func isReadableFile() { + isReadableFileArgs = [atPath] + return true + } + override func fileModificationDate() { + fileModificationDateArgs = [atPath] + return 0 + } + override func fileSize() { + fileSizeArgs = [atPath] + return 0 + } +} +*/ + diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift index 1ce415bc7958..0fcdfae38896 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift @@ -17,12 +17,13 @@ class URLProxyAPIDelegate : PigeonApiDelegateURL { func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse { var isStale: Bool = true let url: URL = try URL(resolvingBookmarkData: data.data, bookmarkDataIsStale: &isStale) - let attr = try FileManager.default.attributesOfItem(atPath: url.path) - print(attr[FileAttributeKey.modificationDate] as? Date as Any) - print(FileManager.default.fileExists(atPath: url.path)) return URLResolvingBookmarkDataResponse(url: url, isStale: isStale) } + func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String { + return pigeonInstance.path + } + func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData { let data = try pigeonInstance.bookmarkData( options: [], diff --git a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart index e114c848e262..a9971bf19c2f 100644 --- a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart +++ b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart @@ -41,6 +41,9 @@ class PigeonOverrides { /// Overrides [FileHandle.forReadingFromUrl]. static FileHandle Function({required URL url})? fileHandle_forReadingFromUrl; + /// Overrides [FileManager.defaultManager]. + static FileManager? fileManager_defaultManager; + /// Overrides [URL.fileURLWithPath]. static Future Function(String)? uRL_fileURLWithPath; @@ -56,6 +59,7 @@ class PigeonOverrides { uRL_fileURLWithPath = null; uRL_resolvingBookmarkData = null; fileHandle_forReadingFromUrl = null; + fileManager_defaultManager = null; } } @@ -168,6 +172,7 @@ class PigeonInstanceManager { URLResolvingBookmarkDataResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); URL.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + FileManager.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -717,6 +722,40 @@ class URL extends PigeonInternalProxyApiBaseClass { } } + Future path() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecURL; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.URL.path'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as String?)!; + } + } + Future bookmarkData( List options, List? keys, @@ -1009,3 +1048,242 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } +class FileManager extends PigeonInternalProxyApiBaseClass { + /// Constructs [FileManager] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + FileManager.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileManager = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static final FileManager _defaultManager = pigeonVar_defaultManager(); + + static FileManager get defaultManager => + PigeonOverrides.fileManager_defaultManager ?? _defaultManager; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + FileManager Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + FileManager.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + static FileManager pigeonVar_defaultManager() { + final FileManager pigeonVar_instance = FileManager.pigeon_detached(); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); + final BinaryMessenger pigeonVar_binaryMessenger = + ServicesBinding.instance.defaultBinaryMessenger; + final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance + .addDartCreatedInstance(pigeonVar_instance); + () async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + return pigeonVar_instance; + } + + Future fileExists(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.fileExists'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future isReadableFile(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future fileModificationDate(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.fileModificationDate'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as int?); + } + } + + Future fileSize(String atPath) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileManager; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileManager.fileSize'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, atPath]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as int?); + } + } + + @override + FileManager pigeon_copy() { + return FileManager.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index a1563b452c6d..1404f75a98d3 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -1,10 +1,11 @@ import 'dart:convert'; -import 'dart:io'; import 'dart:typed_data'; import 'package:cross_file_ios/src/foundation.g.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +// Note for me: Will probs need a `static Future method(Uint8List bookmarkData` method +// instead to create persistent file. base class IOSXFile extends PlatformSharedStorageXFile { IOSXFile(super.params) : super.implementation(); @@ -21,7 +22,6 @@ base class IOSXFile extends PlatformSharedStorageXFile { final URLResolvingBookmarkDataResponse response = await URL .resolvingBookmarkData(bookmarkData, [], null); if (response.isStale) { - // TODO: create new bookmark print('STALE'); return null; } @@ -39,24 +39,50 @@ base class IOSXFile extends PlatformSharedStorageXFile { @override Future canRead() async { final URL? bookmarkUrl = await _bookmarkUrl; - return bookmarkUrl != null; + if (bookmarkUrl case URL bookmarkUrl) { + return FileManager.defaultManager.isReadableFile(await bookmarkUrl.path()); + } + + return false; } @override - Future exists() { - return canRead(); + Future exists() async { + final URL? bookmarkUrl = await _bookmarkUrl; + if (bookmarkUrl case URL bookmarkUrl) { + return FileManager.defaultManager.fileExists(await bookmarkUrl.path()); + } + + return false; } @override - Future lastModified() { - // TODO: implement lastModified - throw UnimplementedError(); + Future lastModified() async { + final URL? bookmarkUrl = await _bookmarkUrl; + if (bookmarkUrl case URL bookmarkUrl) { + final int? lastModifiedSinceEpoch = await FileManager.defaultManager + .fileModificationDate(await bookmarkUrl.path()); + if (lastModifiedSinceEpoch case int lastModifiedSinceEpoch) { + return DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch); + } + } + + throw UnsupportedError('cant read: ${params.path}'); } @override - Future length() { - // TODO: implement length - throw UnimplementedError(); + Future length() async { + final URL? bookmarkUrl = await _bookmarkUrl; + if (bookmarkUrl case URL bookmarkUrl) { + final int? fileSize = await FileManager.defaultManager.fileSize( + await bookmarkUrl.path(), + ); + if (fileSize case int fileSize) { + return fileSize; + } + } + + throw UnsupportedError('cant read: ${params.path}'); } @override diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart index 38c1813b23c1..e50217f75645 100644 --- a/packages/cross_file/cross_file_ios/pigeons/foundation.dart +++ b/packages/cross_file/cross_file_ios/pigeons/foundation.dart @@ -31,6 +31,8 @@ abstract class URL { URL? relativeTo, ); + String path(); + Uint8List bookmarkData( List options, List? keys, @@ -50,3 +52,17 @@ abstract class FileHandle { void close(); } + +@ProxyApi() +abstract class FileManager { + @static + late final FileManager defaultManager; + + bool fileExists(String atPath); + + bool isReadableFile(String atPath); + + int? fileModificationDate(String atPath); + + int? fileSize(String atPath); +} diff --git a/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart b/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart index c9662087f080..0d7c5794e24e 100644 --- a/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart +++ b/packages/file_selector/file_selector_ios/example/lib/open_text_page.dart @@ -30,6 +30,8 @@ class OpenTextPage extends StatelessWidget { print(file.params.path); print(await file.canRead()); print(await file.exists()); + print(await file.lastModified()); + print(await file.length()); final String fileContent = await file.readAsString(); if (context.mounted) { From 8e52ecf3962b049c4d4ab7aa0db51cfb5dd5caae Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:23:48 -0500 Subject: [PATCH 022/398] open read for ios impl --- .../lib/src/android_cross_file.dart | 4 +- .../proxies/FileHandleProxyAPIDelegate.swift | 11 ++++++ .../ios/Classes/proxies/Foundation.g.swift | 38 +++++++++++++++++++ .../cross_file_ios/lib/src/foundation.g.dart | 29 ++++++++++++++ .../lib/src/ios_cross_file.dart | 23 +++++++++-- .../cross_file_ios/pigeons/foundation.dart | 2 + 6 files changed, 102 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index aacda3e6a298..dae2f38ba31b 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -30,7 +30,9 @@ base class AndroidXFile extends PlatformSharedStorageXFile { ); // TODO: add support for start and end. if (inputStream case InputStream inputStream) { - InputStreamReadBytesResponse response = await inputStream.readBytes(1024); + InputStreamReadBytesResponse response = await inputStream.readBytes( + 4 * 1024, + ); while (response.returnValue != -1) { yield response.bytes; response = await inputStream.readBytes(4 * 1024); diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift index 89f6900a3c24..cd2b4dc16c1e 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift @@ -32,4 +32,15 @@ class FileHandleProxyAPIDelegate : PigeonApiDelegateFileHandle { func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { try pigeonInstance.close() } + + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? { + if #available(iOS 13.4, *) { + let data = try pigeonInstance.read(upToCount: Int(count)) + if let data = data { + return FlutterStandardTypedData(bytes: data) + } + } + + return nil + } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift index e97b294822a5..bcbc0139c185 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift @@ -1004,6 +1004,7 @@ class TestURL: URL { protocol PigeonApiDelegateFileHandle { func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } @@ -1042,6 +1043,22 @@ withIdentifier: pigeonIdentifierArg) } else { forReadingFromUrlChannel.setMessageHandler(nil) } + let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + readUpToCountChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + let countArg = args[1] as! Int64 + do { + let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + readUpToCountChannel.setMessageHandler(nil) + } let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) if let api = api { readToEndChannel.setMessageHandler { message, reply in @@ -1126,6 +1143,10 @@ class FileHandleProxyAPIDelegate : PigeonApiDelegateFileHandle { return FileHandle(,url: url) } + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? { + return pigeonInstance.readUpToCount(count: count) + } + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? { return pigeonInstance.readToEnd() } @@ -1157,6 +1178,18 @@ class FileHandleTests: XCTestCase { XCTAssertNotNil(instance) } + func testReadUpToCount() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = TestFileHandle() + let count = 0 + let value = try? api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: instance, count: count) + + XCTAssertEqual(instance.readUpToCountArgs, [count]) + XCTAssertEqual(value, instance.readUpToCount(count: count)) + } + func testReadToEnd() { let registrar = TestProxyApiRegistrar() let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) @@ -1180,10 +1213,15 @@ class FileHandleTests: XCTestCase { } class TestFileHandle: FileHandle { + var readUpToCountArgs: [AnyHashable?]? = nil var readToEndCalled = false var closeCalled = false + override func readUpToCount() { + readUpToCountArgs = [count] + return byteArrayOf(0xA1.toByte()) + } override func readToEnd() { readToEndCalled = true } diff --git a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart index a9971bf19c2f..d49679c068e1 100644 --- a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart +++ b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart @@ -981,6 +981,35 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } + Future readUpToCount(int count) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_ios.FileHandle.readUpToCount'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, count]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as Uint8List?); + } + } + Future readToEnd() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index 1404f75a98d3..0b7542c7fb7e 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -40,7 +40,9 @@ base class IOSXFile extends PlatformSharedStorageXFile { Future canRead() async { final URL? bookmarkUrl = await _bookmarkUrl; if (bookmarkUrl case URL bookmarkUrl) { - return FileManager.defaultManager.isReadableFile(await bookmarkUrl.path()); + return FileManager.defaultManager.isReadableFile( + await bookmarkUrl.path(), + ); } return false; @@ -92,9 +94,22 @@ base class IOSXFile extends PlatformSharedStorageXFile { } @override - Stream> openRead([int? start, int? end]) { - // TODO: implement openRead - throw UnimplementedError(); + Stream> openRead([int? start, int? end]) async* { + if (await _bookmarkUrl case URL url) { + final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); + try { + Uint8List? bytes = await fileHandle.readUpToCount(4 * 1024); + while (bytes != null && bytes.isNotEmpty) { + yield bytes; + // TODO: this is only supported on ios 13.4 + bytes = await fileHandle.readUpToCount(4 * 1024); + } + } finally { + await fileHandle.close(); + } + } else { + throw UnsupportedError('Cant access bytes to file: ${params.path}'); + } } @override diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart index e50217f75645..04bdd79963ac 100644 --- a/packages/cross_file/cross_file_ios/pigeons/foundation.dart +++ b/packages/cross_file/cross_file_ios/pigeons/foundation.dart @@ -48,6 +48,8 @@ abstract class URL { abstract class FileHandle { FileHandle.forReadingFromUrl(URL url); + Uint8List? readUpToCount(int count); + Uint8List? readToEnd(); void close(); From eb0ff17ee489647cb8bb98dedc58359bb2304b27 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 20 Nov 2025 15:27:52 -0500 Subject: [PATCH 023/398] initial flutter create --- packages/cross_file/cross_file_io/.gitignore | 31 +++++++++++ packages/cross_file/cross_file_io/.metadata | 10 ++++ .../cross_file/cross_file_io/CHANGELOG.md | 3 ++ packages/cross_file/cross_file_io/LICENSE | 1 + packages/cross_file/cross_file_io/README.md | 39 ++++++++++++++ .../cross_file_io/analysis_options.yaml | 4 ++ .../cross_file_io/lib/cross_file_io.dart | 5 ++ .../cross_file/cross_file_io/pubspec.yaml | 54 +++++++++++++++++++ .../test/cross_file_io_test.dart | 12 +++++ 9 files changed, 159 insertions(+) create mode 100644 packages/cross_file/cross_file_io/.gitignore create mode 100644 packages/cross_file/cross_file_io/.metadata create mode 100644 packages/cross_file/cross_file_io/CHANGELOG.md create mode 100644 packages/cross_file/cross_file_io/LICENSE create mode 100644 packages/cross_file/cross_file_io/README.md create mode 100644 packages/cross_file/cross_file_io/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_io/lib/cross_file_io.dart create mode 100644 packages/cross_file/cross_file_io/pubspec.yaml create mode 100644 packages/cross_file/cross_file_io/test/cross_file_io_test.dart diff --git a/packages/cross_file/cross_file_io/.gitignore b/packages/cross_file/cross_file_io/.gitignore new file mode 100644 index 000000000000..dd5eb98951f2 --- /dev/null +++ b/packages/cross_file/cross_file_io/.gitignore @@ -0,0 +1,31 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/packages/cross_file/cross_file_io/.metadata b/packages/cross_file/cross_file_io/.metadata new file mode 100644 index 000000000000..c3035525beb4 --- /dev/null +++ b/packages/cross_file/cross_file_io/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "241d31017403dd24234254fe39b5913714462ff5" + channel: "main" + +project_type: package diff --git a/packages/cross_file/cross_file_io/CHANGELOG.md b/packages/cross_file/cross_file_io/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/cross_file/cross_file_io/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_io/LICENSE b/packages/cross_file/cross_file_io/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/cross_file/cross_file_io/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/cross_file/cross_file_io/README.md b/packages/cross_file/cross_file_io/README.md new file mode 100644 index 000000000000..4a260d8d279a --- /dev/null +++ b/packages/cross_file/cross_file_io/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/packages/cross_file/cross_file_io/analysis_options.yaml b/packages/cross_file/cross_file_io/analysis_options.yaml new file mode 100644 index 000000000000..a5744c1cfbe7 --- /dev/null +++ b/packages/cross_file/cross_file_io/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart new file mode 100644 index 000000000000..298576d81397 --- /dev/null +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -0,0 +1,5 @@ +/// A Calculator. +class Calculator { + /// Returns [value] plus 1. + int addOne(int value) => value + 1; +} diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml new file mode 100644 index 000000000000..ada4dc667f15 --- /dev/null +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -0,0 +1,54 @@ +name: cross_file_io +description: "A new Flutter package project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.11.0-146.0.dev + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_io/test/cross_file_io_test.dart b/packages/cross_file/cross_file_io/test/cross_file_io_test.dart new file mode 100644 index 000000000000..541dd06cae17 --- /dev/null +++ b/packages/cross_file/cross_file_io/test/cross_file_io_test.dart @@ -0,0 +1,12 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cross_file_io/cross_file_io.dart'; + +void main() { + test('adds one to input values', () { + final calculator = Calculator(); + expect(calculator.addOne(2), 3); + expect(calculator.addOne(-7), -6); + expect(calculator.addOne(0), 1); + }); +} From dea1eea2fd53f0ac3f6d665293ee9259d7550e0f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 26 Nov 2025 14:18:53 -0500 Subject: [PATCH 024/398] add io stuff yo --- packages/cross_file/cross_file_io/lib/src/cross_file_io.dart | 0 packages/cross_file/cross_file_io/lib/src/io_cross_file.dart | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/cross_file/cross_file_io/lib/src/cross_file_io.dart create mode 100644 packages/cross_file/cross_file_io/lib/src/io_cross_file.dart diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart new file mode 100644 index 000000000000..e69de29bb2d1 From b26162d2c2b5b244ae347622f5103facb0d9ae38 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 26 Nov 2025 14:30:58 -0500 Subject: [PATCH 025/398] formatting --- .../CrossFileAndroidPlugin.kt | 29 +- .../InputStreamReadBytesResponse.kt | 2 +- .../cross_file_android/ProxyApiRegistrar.kt | 14 +- .../proxies/ContentResolverProxyApi.kt | 9 +- .../proxies/DocumentFile.g.kt | 532 +++++++++++------- .../proxies/DocumentFileProxyApi.kt | 8 +- .../proxies/InputStreamProxyApi.kt | 12 +- .../InputStreamReadBytesResponseProxyApi.kt | 8 +- .../CrossFileAndroidPluginTest.kt | 18 +- .../proxies/ContentResolverTest.kt | 6 - .../proxies/DocumentFileTest.kt | 15 +- .../InputStreamReadBytesResponseTest.kt | 6 - .../proxies/InputStreamTest.kt | 10 +- .../plugin_integration_test.dart | 1 - .../cross_file_android/example/lib/main.dart | 8 +- .../example/test/widget_test.dart | 4 +- .../lib/src/document_file.g.dart | 494 +++++++++------- .../cross_file_io/lib/src/cross_file_io.dart | 1 + .../cross_file_io/lib/src/io_cross_file.dart | 1 + .../ios/RunnerTests/FileHandleTests.swift | 4 +- .../ios/RunnerTests/FileManagerTests.swift | 12 +- .../example/ios/RunnerTests/RunnerTests.swift | 1 - ...RLResolvingBookmarkDataResponseTests.swift | 1 - .../example/ios/RunnerTests/UrlTests.swift | 17 +- .../ios/Classes/CrossFileIOSPlugin.swift | 28 +- .../ios/Classes/ProxyAPIDelegate.swift | 31 +- .../URLResolvingBookmarkDataResponse.swift | 3 +- .../proxies/FileHandleProxyAPIDelegate.swift | 18 +- .../proxies/FileManagerProxyAPIDelegate.swift | 28 +- .../ios/Classes/proxies/Foundation.g.swift | 323 +++++++---- .../Classes/proxies/URLProxyAPIDelegate.swift | 28 +- ...BookmarkDataResponseProxyAPIDelegate.swift | 14 +- 32 files changed, 989 insertions(+), 697 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt index 076091bad3c0..841e192fe62c 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt @@ -1,26 +1,21 @@ package dev.flutter.packages.cross_file_android import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.MethodCallHandler -import io.flutter.plugin.common.MethodChannel.Result /** CrossFileAndroidPlugin */ -class CrossFileAndroidPlugin : - FlutterPlugin { +class CrossFileAndroidPlugin : FlutterPlugin { - private lateinit var registrar: ProxyApiRegistrar + private lateinit var registrar: ProxyApiRegistrar - override fun onAttachedToEngine(pluginBinding: FlutterPlugin.FlutterPluginBinding) { - registrar = - ProxyApiRegistrar(pluginBinding.binaryMessenger, context = pluginBinding.applicationContext) - registrar.setUp() - } + override fun onAttachedToEngine(pluginBinding: FlutterPlugin.FlutterPluginBinding) { + registrar = + ProxyApiRegistrar(pluginBinding.binaryMessenger, context = pluginBinding.applicationContext) + registrar.setUp() + } - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { - registrar.ignoreCallsToDart = true - registrar.tearDown() - registrar.instanceManager.clear() - } + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + registrar.ignoreCallsToDart = true + registrar.tearDown() + registrar.instanceManager.clear() + } } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt index 3b552f0fd26f..f88d96e03cf0 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt @@ -18,4 +18,4 @@ data class InputStreamReadBytesResponse(val returnValue: Int, val bytes: ByteArr result = 31 * result + bytes.contentHashCode() return result } -} \ No newline at end of file +} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt index 2ba65081feea..37679e97cfb2 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -2,26 +2,26 @@ package dev.flutter.packages.cross_file_android import android.content.Context import android.os.Build +import android.os.Handler import android.os.Looper import androidx.annotation.ChecksSdkIntAtLeast +import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi import dev.flutter.packages.cross_file_android.proxies.DocumentFilePigeonProxyApiRegistrar +import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi +import dev.flutter.packages.cross_file_android.proxies.InputStreamProxyApi +import dev.flutter.packages.cross_file_android.proxies.InputStreamReadBytesResponseProxyApi import dev.flutter.packages.cross_file_android.proxies.PigeonApiContentResolver import dev.flutter.packages.cross_file_android.proxies.PigeonApiDocumentFile import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStream import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStreamReadBytesResponse import io.flutter.plugin.common.BinaryMessenger -import android.os.Handler -import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi -import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi -import dev.flutter.packages.cross_file_android.proxies.InputStreamProxyApi -import dev.flutter.packages.cross_file_android.proxies.InputStreamReadBytesResponseProxyApi /** * Implementation of [InteractiveMediaAdsLibraryPigeonProxyApiRegistrar] that provides each ProxyApi * implementation and any additional resources needed by an implementation. */ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Context) : - DocumentFilePigeonProxyApiRegistrar(binaryMessenger) { + DocumentFilePigeonProxyApiRegistrar(binaryMessenger) { // Added to be overriden for tests. The test implementation calls `callback` immediately, instead // of waiting for the main thread to run it. @@ -50,4 +50,4 @@ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Cont override fun getPigeonApiInputStream(): PigeonApiInputStream { return InputStreamProxyApi(this) } -} \ No newline at end of file +} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt index dde9ced5b5b6..d83a70785288 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt @@ -12,15 +12,16 @@ import java.io.InputStream /** * ProxyApi implementation for [ContentResolver]. * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. + * This class may handle instantiating native object instances that are attached to a Dart instance + * or handle method calls on the associated native class or an instance of that class. */ -class ContentResolverProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiContentResolver(pigeonRegistrar) { +class ContentResolverProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiContentResolver(pigeonRegistrar) { override fun instance(): ContentResolver { return pigeonRegistrar.context.contentResolver } - override fun openInputStream(pigeon_instance: ContentResolver,uri: String): InputStream? { + override fun openInputStream(pigeon_instance: ContentResolver, uri: String): InputStream? { return pigeon_instance.openInputStream(uri.toUri()) } } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt index 9df80f5cdf4b..bfd84e00cf38 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt @@ -10,16 +10,17 @@ package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object DocumentFilePigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + return FlutterError( + "channel-error", "Unable to establish connection on channel: '$channelName'.", "") + } fun wrapResult(result: Any?): List { return listOf(result) @@ -27,50 +28,48 @@ private object DocumentFilePigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() /** * Maintains instances used to communicate with the corresponding objects in Dart. * - * Objects stored in this container are represented by an object in Dart that is also stored in - * an InstanceManager with the same identifier. + * Objects stored in this container are represented by an object in Dart that is also stored in an + * InstanceManager with the same identifier. * * When an instance is added with an identifier, either can be used to retrieve the other. * - * Added instances are added as a weak reference and a strong reference. When the strong - * reference is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong - * reference is removed and then the identifier is retrieved with the intention to pass the identifier - * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance - * is recreated. The strong reference will then need to be removed manually again. + * Added instances are added as a weak reference and a strong reference. When the strong reference + * is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the + * strong reference is removed and then the identifier is retrieved with the intention to pass the + * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the + * instance is recreated. The strong reference will then need to be removed manually again. */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class DocumentFilePigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ +class DocumentFilePigeonInstanceManager( + private val finalizationListener: PigeonFinalizationListener +) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface PigeonFinalizationListener { fun onFinalize(identifier: Long) } @@ -139,19 +138,20 @@ class DocumentFilePigeonInstanceManager(private val finalizationListener: Pigeon private const val tag = "PigeonInstanceManager" /** - * Instantiate a new manager with a listener for garbage collected weak - * references. + * Instantiate a new manager with a listener for garbage collected weak references. * * When the manager is no longer needed, [stopFinalizationListener] must be called. */ - fun create(finalizationListener: PigeonFinalizationListener): DocumentFilePigeonInstanceManager { + fun create( + finalizationListener: PigeonFinalizationListener + ): DocumentFilePigeonInstanceManager { return DocumentFilePigeonInstanceManager(finalizationListener) } } /** - * Removes `identifier` and return its associated strongly referenced instance, if present, - * from the manager. + * Removes `identifier` and return its associated strongly referenced instance, if present, from + * the manager. */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() @@ -161,15 +161,13 @@ class DocumentFilePigeonInstanceManager(private val finalizationListener: Pigeon /** * Retrieves the identifier paired with an instance, if present, otherwise `null`. * - * * If the manager contains a strong reference to `instance`, it will return the identifier * associated with `instance`. If the manager contains only a weak reference to `instance`, a new * strong reference to `instance` will be added and will need to be removed again with [remove]. * - * * If this method returns a nonnull identifier, this method also expects the Dart - * `DocumentFilePigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - * identifier is associated with. + * `DocumentFilePigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance + * the identifier is associated with. */ fun getIdentifierForStrongReference(instance: Any?): Long? { logWarningIfFinalizationListenerHasStopped() @@ -186,9 +184,9 @@ class DocumentFilePigeonInstanceManager(private val finalizationListener: Pigeon /** * Adds a new instance that was instantiated from Dart. * - * The same instance can be added multiple times, but each identifier must be unique. This - * allows two objects that are equivalent (e.g. the `equals` method returns true and their - * hashcodes are equal) to both be added. + * The same instance can be added multiple times, but each identifier must be unique. This allows + * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are + * equal) to both be added. * * [identifier] must be >= 0 and unique. */ @@ -200,13 +198,15 @@ class DocumentFilePigeonInstanceManager(private val finalizationListener: Pigeon /** * Adds a new unique instance that was instantiated from the host platform. * - * If the manager contains [instance], this returns the corresponding identifier. If the - * manager does not contain [instance], this adds the instance and returns a unique - * identifier for that [instance]. + * If the manager contains [instance], this returns the corresponding identifier. If the manager + * does not contain [instance], this adds the instance and returns a unique identifier for that + * [instance]. */ fun addHostCreatedInstance(instance: Any): Long { logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } + require(!containsInstance(instance)) { + "Instance of ${instance.javaClass} has already been added." + } val identifier = nextIdentifier++ addInstance(instance, identifier) return identifier @@ -290,39 +290,43 @@ class DocumentFilePigeonInstanceManager(private val finalizationListener: Pigeon private fun logWarningIfFinalizationListenerHasStopped() { if (hasFinalizationListenerStopped()) { Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped." - ) + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped.") } } } - /** Generated API for managing the Dart and native `InstanceManager`s. */ private class DocumentFilePigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { companion object { /** The codec used by DocumentFilePigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { - DocumentFilePigeonCodec() - } + val codec: MessageCodec by lazy { DocumentFilePigeonCodec() } /** * Sets up an instance of `DocumentFilePigeonInstanceManagerApi` to handle messages from the * `binaryMessenger`. */ - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: DocumentFilePigeonInstanceManager?) { + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + instanceManager: DocumentFilePigeonInstanceManager? + ) { run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", + codec) if (instanceManager != null) { channel.setMessageHandler { message, reply -> val args = message as List val identifierArg = args[0] as Long - val wrapped: List = try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -330,15 +334,20 @@ private class DocumentFilePigeonInstanceManagerApi(val binaryMessenger: BinaryMe } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", + codec) if (instanceManager != null) { channel.setMessageHandler { _, reply -> - val wrapped: List = try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -348,9 +357,9 @@ private class DocumentFilePigeonInstanceManagerApi(val binaryMessenger: BinaryMe } } - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) -{ - val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(identifierArg)) { if (it is List<*>) { @@ -361,13 +370,13 @@ private class DocumentFilePigeonInstanceManagerApi(val binaryMessenger: BinaryMe } } else { callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } + } } } } /** - * Provides implementations for each ProxyApi implementation and provides access to resources - * needed by any implementation. + * Provides implementations for each ProxyApi implementation and provides access to resources needed + * by any implementation. */ abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { /** Whether APIs should ignore calling to Dart. */ @@ -384,24 +393,23 @@ abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMe init { val api = DocumentFilePigeonInstanceManagerApi(binaryMessenger) - instanceManager = DocumentFilePigeonInstanceManager.create( - object : DocumentFilePigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier" - ) - } - } - } - } - ) + instanceManager = + DocumentFilePigeonInstanceManager.create( + object : DocumentFilePigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier") + } + } + } + }) } /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of - * `DocumentFile` to the Dart `InstanceManager`. + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` + * to the Dart `InstanceManager`. */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile @@ -418,8 +426,8 @@ abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMe abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of - * `InputStream` to the Dart `InstanceManager`. + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to + * the Dart `InstanceManager`. */ abstract fun getPigeonApiInputStream(): PigeonApiInputStream @@ -429,6 +437,7 @@ abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMe PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } + fun tearDown() { DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) @@ -436,17 +445,17 @@ abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMe PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } -private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePigeonProxyApiRegistrar) : DocumentFilePigeonCodec() { + +private class DocumentFilePigeonProxyApiBaseCodec( + val registrar: DocumentFilePigeonProxyApiRegistrar +) : DocumentFilePigeonCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 128.toByte() -> { val identifier: Long = readValue(buffer) as Long val instance: Any? = registrar.instanceManager.getInstance(identifier) if (instance == null) { - Log.e( - "PigeonProxyApiBaseCodec", - "Failed to find instance with identifier: $identifier" - ) + Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") } return instance } @@ -455,16 +464,27 @@ private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePig } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { + if (value is Boolean || + value is ByteArray || + value is Double || + value is DoubleArray || + value is FloatArray || + value is Int || + value is IntArray || + value is List<*> || + value is Long || + value is LongArray || + value is Map<*, *> || + value is String || + value == null) { super.writeValue(stream, value) return } fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception" - ) + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception") } if (value is androidx.documentfile.provider.DocumentFile) { @@ -473,22 +493,19 @@ private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePig logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) } } - } - else if (value is android.content.ContentResolver) { + } else if (value is android.content.ContentResolver) { registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } - else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + } else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) } } - } - else if (value is java.io.InputStream) { + } else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) @@ -501,21 +518,27 @@ private class DocumentFilePigeonProxyApiBaseCodec(val registrar: DocumentFilePig stream.write(128) writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) } - else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") + else -> + throw IllegalArgumentException( + "Unsupported value: '$value' of type '${value.javaClass.name}'") } } } + private open class DocumentFilePigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } @Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { +abstract class PigeonApiDocumentFile( + open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar +) { abstract fun fromSingleUri(path: String): androidx.documentfile.provider.DocumentFile abstract fun canRead(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean @@ -533,18 +556,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val pathArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(pathArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromSingleUri(pathArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -552,16 +581,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -569,16 +603,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -586,16 +623,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -603,16 +643,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -620,16 +665,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -641,16 +689,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" @@ -658,17 +709,17 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: DocumentFilePigeo channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } + } } } } - } /* @@ -800,27 +851,38 @@ class DocumentFileTest { */ /** https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { +abstract class PigeonApiContentResolver( + open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar +) { abstract fun instance(): android.content.ContentResolver - abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? + abstract fun openInputStream( + pigeon_instance: android.content.ContentResolver, + uri: String + ): java.io.InputStream? companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -828,17 +890,22 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePi } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as android.content.ContentResolver val uriArg = args[1] as String - val wrapped: List = try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -850,16 +917,19 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePi @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: android.content.ContentResolver, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" @@ -867,17 +937,17 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: DocumentFilePi channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } + } } } } - } /* @@ -944,43 +1014,56 @@ class ContentResolverTest { } */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { - abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long +abstract class PigeonApiInputStreamReadBytesResponse( + open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar +) { + abstract fun returnValue( + pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + ): Long - abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray + abstract fun bytes( + pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + ): ByteArray @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) -{ + /** + * Creates a Dart instance of InputStreamReadBytesResponse and attaches it to + * [pigeon_instanceArg]. + */ + fun pigeon_newInstance( + pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val returnValueArg = returnValue(pigeon_instanceArg) val bytesArg = bytes(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channelName = + "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } + } } } } - } /* @@ -1056,7 +1139,10 @@ class InputStreamReadBytesResponseTest { */ @Suppress("UNCHECKED_CAST") abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { - abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + abstract fun readBytes( + pigeon_instance: java.io.InputStream, + len: Long + ): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray @@ -1067,17 +1153,22 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val lenArg = args[1] as Long - val wrapped: List = try { - listOf(api.readBytes(pigeon_instanceArg, lenArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readBytes(pigeon_instanceArg, lenArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1085,16 +1176,21 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1102,17 +1198,20 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val nArg = args[1] as Long - val wrapped: List = try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + DocumentFilePigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1124,16 +1223,19 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: java.io.InputStream, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" @@ -1141,17 +1243,17 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeon channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } + } } } } - } /* diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt index 151d96d14d13..cdba1030b671 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt @@ -11,10 +11,11 @@ import dev.flutter.packages.cross_file_android.ProxyApiRegistrar /** * ProxyApi implementation for [DocumentFile]. * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. + * This class may handle instantiating native object instances that are attached to a Dart instance + * or handle method calls on the associated native class or an instance of that class. */ -class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiDocumentFile(pigeonRegistrar) { +class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiDocumentFile(pigeonRegistrar) { override fun fromSingleUri(path: String): DocumentFile { // Only returns null on platforms below Android 19. return DocumentFile.fromSingleUri(pigeonRegistrar.context, path.toUri())!! @@ -39,5 +40,4 @@ class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : Pi override fun length(pigeon_instance: DocumentFile): Long { return pigeon_instance.length() } - } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt index 8dea856bd5d6..eda56173a221 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -4,18 +4,19 @@ package dev.flutter.packages.cross_file_android.proxies -import java.io.InputStream import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse import dev.flutter.packages.cross_file_android.ProxyApiRegistrar +import java.io.InputStream /** * ProxyApi implementation for [InputStream]. * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. + * This class may handle instantiating native object instances that are attached to a Dart instance + * or handle method calls on the associated native class or an instance of that class. */ -class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStream(pigeonRegistrar) { - override fun readBytes(pigeon_instance: InputStream,len: Long): InputStreamReadBytesResponse { +class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiInputStream(pigeonRegistrar) { + override fun readBytes(pigeon_instance: InputStream, len: Long): InputStreamReadBytesResponse { val bytes = ByteArray(len.toInt()) return InputStreamReadBytesResponse(pigeon_instance.read(bytes), bytes) } @@ -27,5 +28,4 @@ class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : Pig override fun skip(pigeon_instance: InputStream, n: Long): Long { return pigeon_instance.skip(n) } - } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt index f0fc309c84e9..925c6f4365e6 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt @@ -10,10 +10,11 @@ import dev.flutter.packages.cross_file_android.ProxyApiRegistrar /** * ProxyApi implementation for [InputStreamReadBytesResponse]. * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. + * This class may handle instantiating native object instances that are attached to a Dart instance + * or handle method calls on the associated native class or an instance of that class. */ -class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStreamReadBytesResponse(pigeonRegistrar) { +class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiInputStreamReadBytesResponse(pigeonRegistrar) { override fun returnValue(pigeon_instance: InputStreamReadBytesResponse): Long { return pigeon_instance.returnValue.toLong() @@ -22,5 +23,4 @@ class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyAp override fun bytes(pigeon_instance: InputStreamReadBytesResponse): ByteArray { return pigeon_instance.bytes } - } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt index 913c6550dbcb..9a0ffc7bca82 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt @@ -2,8 +2,8 @@ package dev.flutter.packages.cross_file_android import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel -import org.mockito.Mockito import kotlin.test.Test +import org.mockito.Mockito /* * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. @@ -14,14 +14,14 @@ import kotlin.test.Test */ internal class CrossFileAndroidPluginTest { - @Test - fun onMethodCall_getPlatformVersion_returnsExpectedValue() { - val plugin = CrossFileAndroidPlugin() + @Test + fun onMethodCall_getPlatformVersion_returnsExpectedValue() { + val plugin = CrossFileAndroidPlugin() - val call = MethodCall("getPlatformVersion", null) - val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) - plugin.onMethodCall(call, mockResult) + val call = MethodCall("getPlatformVersion", null) + val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) + plugin.onMethodCall(call, mockResult) - Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) - } + Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) + } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt index c9425f3ae6c4..97c1f2f9d225 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt @@ -8,12 +8,7 @@ import android.content.ContentResolver import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq import org.mockito.kotlin.mock -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever class ContentResolverTest { @@ -28,5 +23,4 @@ class ContentResolverTest { assertEquals(value, api.openInputStream(instance, uri)) } - } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt index faba0ca1709f..3a4940a99bd9 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -8,11 +8,7 @@ import androidx.documentfile.provider.DocumentFile import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq import org.mockito.kotlin.mock -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever class DocumentFileTest { @@ -31,7 +27,7 @@ class DocumentFileTest { val value = true whenever(instance.canRead()).thenReturn(value) - assertEquals(value, api.canRead(instance )) + assertEquals(value, api.canRead(instance)) } @Test @@ -42,7 +38,7 @@ class DocumentFileTest { val value = true whenever(instance.delete()).thenReturn(value) - assertEquals(value, api.delete(instance )) + assertEquals(value, api.delete(instance)) } @Test @@ -53,7 +49,7 @@ class DocumentFileTest { val value = true whenever(instance.exists()).thenReturn(value) - assertEquals(value, api.exists(instance )) + assertEquals(value, api.exists(instance)) } @Test @@ -64,7 +60,7 @@ class DocumentFileTest { val value = 0 whenever(instance.lastModified()).thenReturn(value) - assertEquals(value, api.lastModified(instance )) + assertEquals(value, api.lastModified(instance)) } @Test @@ -75,7 +71,6 @@ class DocumentFileTest { val value = 0 whenever(instance.length()).thenReturn(value) - assertEquals(value, api.length(instance )) + assertEquals(value, api.length(instance)) } - } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt index 2816e1a60605..7e3c46dde5e3 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt @@ -7,12 +7,7 @@ package dev.flutter.packages.cross_file_android.proxies import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq import org.mockito.kotlin.mock -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever class InputStreamReadBytesResponseTest { @@ -37,5 +32,4 @@ class InputStreamReadBytesResponseTest { assertEquals(value, api.bytes(instance)) } - } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index 5de61ff58581..ad955044dbf1 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -4,16 +4,11 @@ package dev.flutter.packages.cross_file_android.proxies -import java.io.InputStream import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq import org.mockito.kotlin.mock -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever class InputStreamTest { @@ -37,7 +32,6 @@ class InputStreamTest { val value = byteArrayOf(0xA1.toByte()) whenever(instance.readAllBytes()).thenReturn(value) - assertEquals(value, api.readAllBytes(instance )) + assertEquals(value, api.readAllBytes(instance)) } - } diff --git a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart index e0bc36a40144..ab1e84facf3a 100644 --- a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart +++ b/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart @@ -6,7 +6,6 @@ // For more information about Flutter integration tests, please see // https://flutter.dev/to/integration-testing - import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 976818e5ef1d..b5079f60b5e8 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -23,12 +23,8 @@ class _MyAppState extends State { Widget build(BuildContext context) { return MaterialApp( home: Scaffold( - appBar: AppBar( - title: const Text('Plugin example app'), - ), - body: Center( - child: Text('Running on: $_platformVersion\n'), - ), + appBar: AppBar(title: const Text('Plugin example app')), + body: Center(child: Text('Running on: $_platformVersion\n')), ), ); } diff --git a/packages/cross_file/cross_file_android/example/test/widget_test.dart b/packages/cross_file/cross_file_android/example/test/widget_test.dart index 930511fbd8d4..0cbf4761df4a 100644 --- a/packages/cross_file/cross_file_android/example/test/widget_test.dart +++ b/packages/cross_file/cross_file_android/example/test/widget_test.dart @@ -18,8 +18,8 @@ void main() { // Verify that platform version is retrieved. expect( find.byWidgetPredicate( - (Widget widget) => widget is Text && - widget.data!.startsWith('Running on:'), + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), ), findsOneWidget, ); diff --git a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart index 962b53a3c47f..cb367ce53273 100644 --- a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/document_file.g.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' + show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -20,7 +21,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -29,6 +34,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -40,7 +46,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String path})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -64,7 +70,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -134,9 +140,10 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; + final Map> + _weakInstances = >{}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -149,7 +156,8 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = + _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -157,11 +165,21 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager, + ); + DocumentFile.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + ContentResolver.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStream.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -178,8 +196,9 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference( + instance, + ); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -240,15 +259,21 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference( + int identifier, + ) { + final PigeonInternalProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance + .pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = + WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -270,7 +295,10 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + void addHostCreatedInstance( + PigeonInternalProxyApiBaseClass instance, + int identifier, + ) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -299,7 +327,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -311,31 +339,37 @@ class _PigeonInternalInstanceManagerApi { PigeonInstanceManager? instanceManager, }) { { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', + ); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + assert( + arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', + ); try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); + (instanceManager ?? PigeonInstanceManager.instance).remove( + arg_identifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -347,12 +381,13 @@ class _PigeonInternalInstanceManagerApi { 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -376,10 +411,10 @@ class _PigeonInternalInstanceManagerApi { 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -398,30 +433,30 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference( + readValue(buffer)! as int, + ); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -443,6 +478,7 @@ class _PigeonCodec extends StandardMessageCodec { } } } + class DocumentFile extends PigeonInternalProxyApiBaseClass { factory DocumentFile.fromSingleUri({ BinaryMessenger? pigeon_binaryMessenger, @@ -465,8 +501,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String path, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -474,12 +510,13 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, path], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier, path]); () async { final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; @@ -518,41 +555,47 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -567,12 +610,13 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.DocumentFile.canRead'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -601,12 +645,13 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.DocumentFile.delete'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -635,12 +680,13 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.DocumentFile.exists'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -669,12 +715,13 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -703,12 +750,13 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.DocumentFile.length'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -766,41 +814,47 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -821,12 +875,13 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.ContentResolver.instance'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -852,12 +907,13 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, uri], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, uri]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -903,56 +959,64 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function( - int returnValue, - Uint8List bytes, - )? pigeon_newInstance, + InputStreamReadBytesResponse Function(int returnValue, Uint8List bytes)? + pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', + ); final int? arg_returnValue = (args[1] as int?); - assert(arg_returnValue != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_returnValue != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', + ); final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert(arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); + assert( + arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - returnValue: arg_returnValue!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: arg_returnValue!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -992,41 +1056,47 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + final BasicMessageChannel + pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1041,12 +1111,13 @@ class InputStream extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.InputStream.readBytes'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, len], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, len]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -1075,12 +1146,13 @@ class InputStream extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -1109,12 +1181,13 @@ class InputStream extends PigeonInternalProxyApiBaseClass { 'dev.flutter.pigeon.cross_file_android.InputStream.skip'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, n], ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, n]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -1143,4 +1216,3 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } - diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index e69de29bb2d1..8b137891791f 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -0,0 +1 @@ + diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index e69de29bb2d1..8b137891791f 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -0,0 +1 @@ + diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift index 67dd7092dfc6..4b06862f67da 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - import Flutter import XCTest @@ -22,7 +21,7 @@ class FileHandleTests: XCTestCase { let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) let instance = TestFileHandle() - let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance ) + let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance) XCTAssertTrue(instance.readToEndCalled) XCTAssertEqual(value, instance.readToEnd()) @@ -32,7 +31,6 @@ class FileHandleTests: XCTestCase { class TestFileHandle: FileHandle { var readToEndCalled = false - override func readToEnd() { readToEndCalled = true } diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift index cc9f5db3c4f2..e71ae793c861 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import Foundation import Flutter +import Foundation import XCTest @testable import cross_file_ios @@ -15,7 +15,8 @@ class FileManagerTests: XCTestCase { let instance = TestFileManager() let path = "myString" - let value = try? api.pigeonDelegate.fileExistsAtPath(pigeonApi: api, pigeonInstance: instance, path: path) + let value = try? api.pigeonDelegate.fileExistsAtPath( + pigeonApi: api, pigeonInstance: instance, path: path) XCTAssertEqual(instance.fileExistsAtPathArgs, [path]) XCTAssertEqual(value, instance.fileExistsAtPath(path: path)) @@ -27,7 +28,8 @@ class FileManagerTests: XCTestCase { let instance = TestFileManager() let path = "myString" - let value = try? api.pigeonDelegate.isReadableFileAtPath(pigeonApi: api, pigeonInstance: instance, path: path) + let value = try? api.pigeonDelegate.isReadableFileAtPath( + pigeonApi: api, pigeonInstance: instance, path: path) XCTAssertEqual(instance.isReadableFileAtPathArgs, [path]) XCTAssertEqual(value, instance.isReadableFileAtPath(path: path)) @@ -39,7 +41,8 @@ class FileManagerTests: XCTestCase { let instance = TestFileManager() let path = "myString" - let value = try? api.pigeonDelegate.contentsAtPath(pigeonApi: api, pigeonInstance: instance, path: path) + let value = try? api.pigeonDelegate.contentsAtPath( + pigeonApi: api, pigeonInstance: instance, path: path) XCTAssertEqual(instance.contentsAtPathArgs, [path]) XCTAssertEqual(value, instance.contentsAtPath(path: path)) @@ -51,7 +54,6 @@ class TestFileManager: FileManager { var isReadableFileAtPathArgs: [AnyHashable?]? = nil var contentsAtPathArgs: [AnyHashable?]? = nil - override func fileExistsAtPath() { fileExistsAtPathArgs = [path] return true diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift index f530c51068f3..5440378e39bc 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift @@ -2,7 +2,6 @@ import Flutter import UIKit import XCTest - @testable import cross_file_ios // This demonstrates a simple unit test of the Swift portion of this plugin's implementation. diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift index 0b3d850baefa..c0c72062fe15 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - import Flutter import XCTest diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift index 333a0e59a293..348d9218779b 100644 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift +++ b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - import Flutter import XCTest @@ -14,7 +13,7 @@ class URLTests: XCTestCase { let api = registrar.apiDelegate.pigeonApiURL(registrar) let instance = TestURL() - let value = try? api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: instance ) + let value = try? api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: instance) XCTAssertTrue(instance.pathCalled) XCTAssertEqual(value, instance.path()) @@ -28,10 +27,13 @@ class URLTests: XCTestCase { let options = [.minimalBookmark] let keys = [.isDirectoryKey] let relativeTo = TestURL - let value = try? api.pigeonDelegate.bookmarkData(pigeonApi: api, pigeonInstance: instance, options: options, keys: keys, relativeTo: relativeTo) + let value = try? api.pigeonDelegate.bookmarkData( + pigeonApi: api, pigeonInstance: instance, options: options, keys: keys, relativeTo: relativeTo + ) XCTAssertEqual(instance.bookmarkDataArgs, [options, keys, relativeTo]) - XCTAssertEqual(value, instance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo)) + XCTAssertEqual( + value, instance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo)) } func testStartAccessingSecurityScopedResource() { @@ -39,7 +41,8 @@ class URLTests: XCTestCase { let api = registrar.apiDelegate.pigeonApiURL(registrar) let instance = TestURL() - let value = try? api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) + let value = try? api.pigeonDelegate.startAccessingSecurityScopedResource( + pigeonApi: api, pigeonInstance: instance) XCTAssertTrue(instance.startAccessingSecurityScopedResourceCalled) XCTAssertEqual(value, instance.startAccessingSecurityScopedResource()) @@ -50,7 +53,8 @@ class URLTests: XCTestCase { let api = registrar.apiDelegate.pigeonApiURL(registrar) let instance = TestURL() - try? api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) + try? api.pigeonDelegate.stopAccessingSecurityScopedResource( + pigeonApi: api, pigeonInstance: instance) XCTAssertTrue(instance.stopAccessingSecurityScopedResourceCalled) } @@ -62,7 +66,6 @@ class TestURL: URL { var startAccessingSecurityScopedResourceCalled = false var stopAccessingSecurityScopedResourceCalled = false - override func path() { pathCalled = true } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift index 14c550c01001..50a22460adf0 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift @@ -4,20 +4,20 @@ import UIKit public class CrossFileIOSPlugin: NSObject, FlutterPlugin { var proxyApiRegistrar: FoundationPigeonProxyApiRegistrar? - init(binaryMessenger: FlutterBinaryMessenger) { - proxyApiRegistrar = FoundationPigeonProxyApiRegistrar( - binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) - proxyApiRegistrar?.setUp() - } + init(binaryMessenger: FlutterBinaryMessenger) { + proxyApiRegistrar = FoundationPigeonProxyApiRegistrar( + binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) + proxyApiRegistrar?.setUp() + } - public static func register(with registrar: FlutterPluginRegistrar) { - let plugin = CrossFileIOSPlugin(binaryMessenger: registrar.messenger()) - registrar.publish(plugin) - } + public static func register(with registrar: FlutterPluginRegistrar) { + let plugin = CrossFileIOSPlugin(binaryMessenger: registrar.messenger()) + registrar.publish(plugin) + } - public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - proxyApiRegistrar!.ignoreCallsToDart = true - proxyApiRegistrar!.tearDown() - proxyApiRegistrar = nil - } + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + proxyApiRegistrar!.ignoreCallsToDart = true + proxyApiRegistrar!.tearDown() + proxyApiRegistrar = nil + } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift index e323b97de616..4cedb4f39948 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift @@ -4,27 +4,30 @@ import Foundation /// and any additional resources needed by an implementation. open class ProxyApiDelegate: FoundationPigeonProxyApiDelegate { /// Creates an error when the constructor of a class returns null. - func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { - return PigeonError( - code: "ConstructorReturnedNullError", - message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", - details: nil) - } - + func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { + return PigeonError( + code: "ConstructorReturnedNullError", + message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", + details: nil) + } + func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL { return PigeonApiURL(pigeonRegistrar: registrar, delegate: URLProxyAPIDelegate()) } - + func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle { return PigeonApiFileHandle(pigeonRegistrar: registrar, delegate: FileHandleProxyAPIDelegate()) } - - func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURLResolvingBookmarkDataResponse { - return PigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar: registrar, delegate: URLResolvingBookmarkDataResponseProxyAPIDelegate()) + + func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) + -> PigeonApiURLResolvingBookmarkDataResponse + { + return PigeonApiURLResolvingBookmarkDataResponse( + pigeonRegistrar: registrar, delegate: URLResolvingBookmarkDataResponseProxyAPIDelegate()) } - - func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager { + + func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager + { return PigeonApiFileManager(pigeonRegistrar: registrar, delegate: FileManagerProxyAPIDelegate()) } } - diff --git a/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift b/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift index 4c7a0cd3ee70..29c3b47163b7 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift @@ -1,10 +1,9 @@ class URLResolvingBookmarkDataResponse { let url: URL let isStale: Bool - + init(url: URL, isStale: Bool) { self.url = url self.isStale = isStale } } - diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift index cd2b4dc16c1e..e2942a2231c1 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift @@ -9,38 +9,42 @@ import Foundation /// /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. -class FileHandleProxyAPIDelegate : PigeonApiDelegateFileHandle { +class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle { return try FileHandle(forReadingFrom: url) } - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? { + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws + -> FlutterStandardTypedData? + { var bytes: Data? if #available(iOS 13.4, *) { bytes = try pigeonInstance.readToEnd() } else { bytes = pigeonInstance.readDataToEndOfFile() } - + if let bytes = bytes { return FlutterStandardTypedData(bytes: bytes) } - + return nil } func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { try pigeonInstance.close() } - - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? { + + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) + throws -> FlutterStandardTypedData? + { if #available(iOS 13.4, *) { let data = try pigeonInstance.read(upToCount: Int(count)) if let data = data { return FlutterStandardTypedData(bytes: data) } } - + return nil } } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift index b35d1229aa30..781a9ebdb156 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift @@ -8,30 +8,40 @@ import Foundation /// /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. -class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { +class FileManagerProxyAPIDelegate: PigeonApiDelegateFileManager { func defaultManager(pigeonApi: PigeonApiFileManager) -> FileManager { return FileManager.default } - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) + throws -> Bool + { return pigeonInstance.fileExists(atPath: atPath) } - - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { + + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) + throws -> Bool + { return pigeonInstance.isReadableFile(atPath: atPath) } - func fileModificationDate(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { - let attributes: NSDictionary = try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary + func fileModificationDate( + pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String + ) throws -> Int64? { + let attributes: NSDictionary = + try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary if let date = attributes.fileModificationDate() { return Int64(date.timeIntervalSince1970 * 1000) } - + return nil } - func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { - let attributes: NSDictionary = try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary + func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws + -> Int64? + { + let attributes: NSDictionary = + try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary return Int64(attributes.fileSize()) } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift index bcbc0139c185..523feb6d73a7 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift @@ -59,7 +59,9 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -77,7 +79,6 @@ protocol FoundationPigeonInternalFinalizerDelegate: AnyObject { func onDeinit(identifier: Int64) } - // Attaches to an object to receive a callback when the object is deallocated. internal final class FoundationPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -100,7 +101,8 @@ internal final class FoundationPigeonInternalFinalizer { } static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? FoundationPigeonInternalFinalizer + let finalizer = + objc_getAssociatedObject(instance, associatedObjectKey) as? FoundationPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -112,7 +114,6 @@ internal final class FoundationPigeonInternalFinalizer { } } - /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -216,7 +217,8 @@ final class FoundationPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - FoundationPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + FoundationPigeonInternalFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -297,7 +299,6 @@ final class FoundationPigeonInstanceManager { } } - private class FoundationPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { FoundationPigeonCodec.shared } @@ -310,9 +311,13 @@ private class FoundationPigeonInstanceManagerApi { } /// Sets up an instance of `FoundationPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: FoundationPigeonInstanceManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, instanceManager: FoundationPigeonInstanceManager? + ) { let codec = FoundationPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -327,7 +332,9 @@ private class FoundationPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.clear", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -343,9 +350,13 @@ private class FoundationPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -365,7 +376,8 @@ private class FoundationPigeonInstanceManagerApi { protocol FoundationPigeonProxyApiDelegate { /// An implementation of [PigeonApiURLResolvingBookmarkDataResponse] used to add a new Dart instance of /// `URLResolvingBookmarkDataResponse` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURLResolvingBookmarkDataResponse + func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) + -> PigeonApiURLResolvingBookmarkDataResponse /// An implementation of [PigeonApiURL] used to add a new Dart instance of /// `URL` to the Dart `InstanceManager` and make calls to Dart. func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL @@ -415,13 +427,18 @@ open class FoundationPigeonProxyApiRegistrar { } func setUp() { - FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiURL(self)) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) - PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileManager(self)) + FoundationPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiURL.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiURL(self)) + PigeonApiFileHandle.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + PigeonApiFileManager.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileManager(self)) } func tearDown() { - FoundationPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + FoundationPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) @@ -463,57 +480,62 @@ private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandard } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String || value is URLBookmarkCreationOptions || value is URLResourceKeyEnum || value is URLBookmarkResolutionOptions { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + || value is URLBookmarkCreationOptions || value is URLResourceKeyEnum + || value is URLBookmarkResolutionOptions + { super.writeValue(value) return } - if let instance = value as? URLResolvingBookmarkDataResponse { - pigeonRegistrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } + pigeonRegistrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - if let instance = value as? URL { pigeonRegistrar.apiDelegate.pigeonApiURL(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - if let instance = value as? FileHandle { pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - if let instance = value as? FileManager { pigeonRegistrar.apiDelegate.pigeonApiFileManager(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -613,38 +635,55 @@ class FoundationPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { } protocol PigeonApiDelegateURLResolvingBookmarkDataResponse { - func url(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> URL - func isStale(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> Bool + func url( + pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, + pigeonInstance: URLResolvingBookmarkDataResponse + ) throws -> URL + func isStale( + pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, + pigeonInstance: URLResolvingBookmarkDataResponse + ) throws -> Bool } protocol PigeonApiProtocolURLResolvingBookmarkDataResponse { } -final class PigeonApiURLResolvingBookmarkDataResponse: PigeonApiProtocolURLResolvingBookmarkDataResponse { +final class PigeonApiURLResolvingBookmarkDataResponse: + PigeonApiProtocolURLResolvingBookmarkDataResponse +{ unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateURLResolvingBookmarkDataResponse - init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateURLResolvingBookmarkDataResponse) { + init( + pigeonRegistrar: FoundationPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateURLResolvingBookmarkDataResponse + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } ///Creates a Dart instance of URLResolvingBookmarkDataResponse and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: URLResolvingBookmarkDataResponse, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: URLResolvingBookmarkDataResponse, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let urlArg = try! pigeonDelegate.url(pigeonApi: self, pigeonInstance: pigeonInstance) let isStaleArg = try! pigeonDelegate.isStale(pigeonApi: self, pigeonInstance: pigeonInstance) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg, urlArg, isStaleArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -725,17 +764,24 @@ class URLResolvingBookmarkDataResponseTests: XCTestCase { protocol PigeonApiDelegateURL { func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? - func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse + func resolvingBookmarkData( + pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, + options: [URLBookmarkResolutionOptions], relativeTo: URL? + ) throws -> URLResolvingBookmarkDataResponse func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String - func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool + func bookmarkData( + pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], + keys: [URLResourceKeyEnum]?, relativeTo: URL? + ) throws -> FlutterStandardTypedData + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws + -> Bool func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws } protocol PigeonApiProtocolURL { } -final class PigeonApiURL: PigeonApiProtocolURL { +final class PigeonApiURL: PigeonApiProtocolURL { unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateURL init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateURL) { @@ -746,9 +792,12 @@ final class PigeonApiURL: PigeonApiProtocolURL { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let fileURLWithPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.fileURLWithPath", binaryMessenger: binaryMessenger, codec: codec) + let fileURLWithPathChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.URL.fileURLWithPath", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileURLWithPathChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -763,7 +812,9 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { fileURLWithPathChannel.setMessageHandler(nil) } - let resolvingBookmarkDataChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.resolvingBookmarkData", binaryMessenger: binaryMessenger, codec: codec) + let resolvingBookmarkDataChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.URL.resolvingBookmarkData", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { resolvingBookmarkDataChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -771,7 +822,8 @@ final class PigeonApiURL: PigeonApiProtocolURL { let optionsArg = args[1] as! [URLBookmarkResolutionOptions] let relativeToArg: URL? = nilOrValue(args[2]) do { - let result = try api.pigeonDelegate.resolvingBookmarkData(pigeonApi: api, data: dataArg, options: optionsArg, relativeTo: relativeToArg) + let result = try api.pigeonDelegate.resolvingBookmarkData( + pigeonApi: api, data: dataArg, options: optionsArg, relativeTo: relativeToArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -780,13 +832,16 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { resolvingBookmarkDataChannel.setMessageHandler(nil) } - let pathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.path", binaryMessenger: binaryMessenger, codec: codec) + let pathChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.URL.path", binaryMessenger: binaryMessenger, + codec: codec) if let api = api { pathChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! URL do { - let result = try api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.path( + pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -795,7 +850,9 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { pathChannel.setMessageHandler(nil) } - let bookmarkDataChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.bookmarkData", binaryMessenger: binaryMessenger, codec: codec) + let bookmarkDataChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.URL.bookmarkData", binaryMessenger: binaryMessenger, + codec: codec) if let api = api { bookmarkDataChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -804,7 +861,9 @@ final class PigeonApiURL: PigeonApiProtocolURL { let keysArg: [URLResourceKeyEnum]? = nilOrValue(args[2]) let relativeToArg: URL? = nilOrValue(args[3]) do { - let result = try api.pigeonDelegate.bookmarkData(pigeonApi: api, pigeonInstance: pigeonInstanceArg, options: optionsArg, keys: keysArg, relativeTo: relativeToArg) + let result = try api.pigeonDelegate.bookmarkData( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, options: optionsArg, keys: keysArg, + relativeTo: relativeToArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -813,13 +872,16 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { bookmarkDataChannel.setMessageHandler(nil) } - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource", binaryMessenger: binaryMessenger, codec: codec) + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! URL do { - let result = try api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.startAccessingSecurityScopedResource( + pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -828,13 +890,16 @@ final class PigeonApiURL: PigeonApiProtocolURL { } else { startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) } - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource", binaryMessenger: binaryMessenger, codec: codec) + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! URL do { - try api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + try api.pigeonDelegate.stopAccessingSecurityScopedResource( + pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -846,21 +911,25 @@ final class PigeonApiURL: PigeonApiProtocolURL { } ///Creates a Dart instance of URL and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: URL, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: URL, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -1004,28 +1073,35 @@ class TestURL: URL { protocol PigeonApiDelegateFileHandle { func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) + throws -> FlutterStandardTypedData? + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws + -> FlutterStandardTypedData? func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } protocol PigeonApiProtocolFileHandle { } -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateFileHandle init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let forReadingFromUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.forReadingFromUrl", binaryMessenger: binaryMessenger, codec: codec) + let forReadingFromUrlChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileHandle.forReadingFromUrl", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { forReadingFromUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -1033,8 +1109,8 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { let urlArg = args[1] as! URL do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( -try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), -withIdentifier: pigeonIdentifierArg) + try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -1043,14 +1119,17 @@ withIdentifier: pigeonIdentifierArg) } else { forReadingFromUrlChannel.setMessageHandler(nil) } - let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) + let readUpToCountChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readUpToCount", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readUpToCountChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let countArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + let result = try api.pigeonDelegate.readUpToCount( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -1059,13 +1138,16 @@ withIdentifier: pigeonIdentifierArg) } else { readUpToCountChannel.setMessageHandler(nil) } - let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) + let readToEndChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readToEndChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.readToEnd( + pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -1074,7 +1156,9 @@ withIdentifier: pigeonIdentifierArg) } else { readToEndChannel.setMessageHandler(nil) } - let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) + let closeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileHandle.close", binaryMessenger: binaryMessenger, + codec: codec) if let api = api { closeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -1092,21 +1176,25 @@ withIdentifier: pigeonIdentifierArg) } ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: FileHandle, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -1233,35 +1321,47 @@ class TestFileHandle: FileHandle { protocol PigeonApiDelegateFileManager { func defaultManager(pigeonApi: PigeonApiFileManager) throws -> FileManager - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool - func fileModificationDate(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? - func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? + func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) + throws -> Bool + func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) + throws -> Bool + func fileModificationDate( + pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String + ) throws -> Int64? + func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws + -> Int64? } protocol PigeonApiProtocolFileManager { } -final class PigeonApiFileManager: PigeonApiProtocolFileManager { +final class PigeonApiFileManager: PigeonApiProtocolFileManager { unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateFileManager init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileManager) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileManager? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let defaultManagerChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager", binaryMessenger: binaryMessenger, codec: codec) + let defaultManagerChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { defaultManagerChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 do { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(try api.pigeonDelegate.defaultManager(pigeonApi: api), withIdentifier: pigeonIdentifierArg) + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.defaultManager(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -1270,14 +1370,17 @@ final class PigeonApiFileManager: PigeonApiProtocolFileManager { } else { defaultManagerChannel.setMessageHandler(nil) } - let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileExists", binaryMessenger: binaryMessenger, codec: codec) + let fileExistsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileExists", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileExistsChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileManager let atPathArg = args[1] as! String do { - let result = try api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + let result = try api.pigeonDelegate.fileExists( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -1286,14 +1389,17 @@ final class PigeonApiFileManager: PigeonApiProtocolFileManager { } else { fileExistsChannel.setMessageHandler(nil) } - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile", binaryMessenger: binaryMessenger, codec: codec) + let isReadableFileChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileManager let atPathArg = args[1] as! String do { - let result = try api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + let result = try api.pigeonDelegate.isReadableFile( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -1302,14 +1408,17 @@ final class PigeonApiFileManager: PigeonApiProtocolFileManager { } else { isReadableFileChannel.setMessageHandler(nil) } - let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileModificationDate", binaryMessenger: binaryMessenger, codec: codec) + let fileModificationDateChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileModificationDate", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileModificationDateChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileManager let atPathArg = args[1] as! String do { - let result = try api.pigeonDelegate.fileModificationDate(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + let result = try api.pigeonDelegate.fileModificationDate( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -1318,14 +1427,17 @@ final class PigeonApiFileManager: PigeonApiProtocolFileManager { } else { fileModificationDateChannel.setMessageHandler(nil) } - let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileSize", binaryMessenger: binaryMessenger, codec: codec) + let fileSizeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileSize", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileSizeChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileManager let atPathArg = args[1] as! String do { - let result = try api.pigeonDelegate.fileSize(pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) + let result = try api.pigeonDelegate.fileSize( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -1337,21 +1449,25 @@ final class PigeonApiFileManager: PigeonApiProtocolFileManager { } ///Creates a Dart instance of FileManager and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileManager, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: FileManager, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -1493,4 +1609,3 @@ class TestFileManager: FileManager { } } */ - diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift index 0fcdfae38896..fafcc59dcea6 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift @@ -9,35 +9,43 @@ import Foundation /// /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. -class URLProxyAPIDelegate : PigeonApiDelegateURL { +class URLProxyAPIDelegate: PigeonApiDelegateURL { func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? { return URL(fileURLWithPath: path) } - - func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse { + + func resolvingBookmarkData( + pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, + options: [URLBookmarkResolutionOptions], relativeTo: URL? + ) throws -> URLResolvingBookmarkDataResponse { var isStale: Bool = true let url: URL = try URL(resolvingBookmarkData: data.data, bookmarkDataIsStale: &isStale) return URLResolvingBookmarkDataResponse(url: url, isStale: isStale) } - + func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String { return pigeonInstance.path } - - func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData { + + func bookmarkData( + pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], + keys: [URLResourceKeyEnum]?, relativeTo: URL? + ) throws -> FlutterStandardTypedData { let data = try pigeonInstance.bookmarkData( options: [], includingResourceValuesForKeys: nil, relativeTo: relativeTo ) - + return FlutterStandardTypedData(bytes: data) } - - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool { + + func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws + -> Bool + { return pigeonInstance.startAccessingSecurityScopedResource() } - + func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws { pigeonInstance.stopAccessingSecurityScopedResource() } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift index b138038c218a..6b455e816efa 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift @@ -8,12 +8,20 @@ import Foundation /// /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. -class URLResolvingBookmarkDataResponseProxyAPIDelegate : PigeonApiDelegateURLResolvingBookmarkDataResponse { - func url(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> URL { +class URLResolvingBookmarkDataResponseProxyAPIDelegate: + PigeonApiDelegateURLResolvingBookmarkDataResponse +{ + func url( + pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, + pigeonInstance: URLResolvingBookmarkDataResponse + ) throws -> URL { return pigeonInstance.url } - func isStale(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> Bool { + func isStale( + pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, + pigeonInstance: URLResolvingBookmarkDataResponse + ) throws -> Bool { return pigeonInstance.isStale } From bb9b3b76d5aaa8503457ba9ef0b1c45628ec51b4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Dec 2025 14:22:36 -0500 Subject: [PATCH 026/398] start of working on app facing --- .../cross_file/cross_file/lib/src/cross_file.dart | 13 +++++++++++++ packages/cross_file/cross_file/pubspec.yaml | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 packages/cross_file/cross_file/lib/src/cross_file.dart diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart new file mode 100644 index 000000000000..2081d9c775b1 --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -0,0 +1,13 @@ +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +@immutable +class XFile { + XFile(String path) : this.fromPlatformCreationParams(Pl); + + XFile.fromPlatformCreationParams(PlatformXFileCreationParams params) + : this.fromPlatform(PlatformXFile(params)); + + XFile.fromPlatform(this.platform); + + final PlatformXFile platform; +} diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index 8b05c8bf69a7..a7e06edaa942 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -8,6 +8,8 @@ environment: sdk: ^3.8.0 dependencies: + cross_file_platform_interface: + path: ../cross_file_platform_interface meta: ^1.3.0 web: ">=0.5.1 <2.0.0" From cf28ca68d2264b9e708751aec93b8260e17182df Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:14:48 -0500 Subject: [PATCH 027/398] the app facing impl --- .../cross_file/lib/src/cross_file.dart | 48 ++++++++++++++++++- .../lib/src/shared_storage_cross_file.dart | 26 ++++++++++ packages/cross_file/cross_file/pubspec.yaml | 2 +- 3 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 2081d9c775b1..a27d2a78cd6e 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -1,8 +1,15 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:flutter/foundation.dart' show immutable; + import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:meta/meta.dart'; @immutable -class XFile { - XFile(String path) : this.fromPlatformCreationParams(Pl); +@optionalTypeArgs +class XFile { + XFile(String path) + : this.fromPlatformCreationParams(PlatformXFileCreationParams(path: path)); XFile.fromPlatformCreationParams(PlatformXFileCreationParams params) : this.fromPlatform(PlatformXFile(params)); @@ -10,4 +17,41 @@ class XFile { XFile.fromPlatform(this.platform); final PlatformXFile platform; + + String get path => platform.params.path; + + /// Provides a nonnull platform class extension. + /// + /// Will throw an exception if the specified platform extension can not be + /// returned. + S getPlatformExtension() { + return platform.extension! as S; + } + + /// Attempt to provide the platform class extension. + /// + /// Returns null if the specified platform extension cannot be retrieved. + S? maybeGetPlatformExtension() { + return platform.extension is S ? platform.extension! as S : null; + } + + Future lastModified() => platform.lastModified(); + + /// The length of the file. + Future length() => platform.length(); + + /// Whether file exists. + Future exists() => platform.exists(); + + Future canRead() => platform.canRead(); + + Stream> openRead([int? start, int? end]) => + platform.openRead(start, end); + + /// Reads the entire file contents as a list of bytes. + Future readAsBytes() => platform.readAsBytes(); + + /// Reads the entire file contents as a string using the given Encoding. + Future readAsString({Encoding encoding = utf8}) => + platform.readAsString(encoding: encoding); } diff --git a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart new file mode 100644 index 000000000000..fa951368a4d6 --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart @@ -0,0 +1,26 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:flutter/foundation.dart' show immutable; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'cross_file.dart'; + +@immutable +class SharedStorageXFile extends XFile { + SharedStorageXFile(String path) + : this.fromPlatformCreationParams( + PlatformSharedStorageXFileCreationParams(path: path), + ); + + SharedStorageXFile.fromPlatformCreationParams( + PlatformSharedStorageXFileCreationParams params, + ) : this.fromPlatform(PlatformSharedStorageXFile(params)); + + SharedStorageXFile.fromPlatform(this.platform) : super.fromPlatform(platform); + + @override + final PlatformSharedStorageXFile platform; + + Future delete() => platform.delete(); +} diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index a7e06edaa942..5b2884706814 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -10,7 +10,7 @@ environment: dependencies: cross_file_platform_interface: path: ../cross_file_platform_interface - meta: ^1.3.0 + meta: ^1.17.0 web: ">=0.5.1 <2.0.0" dev_dependencies: From 4eaac7cc00ee6cfe98365e97d6c97925c805719f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Dec 2025 19:14:12 -0500 Subject: [PATCH 028/398] implement io impl --- .../cross_file_io/lib/cross_file_io.dart | 7 +-- .../cross_file_io/lib/src/cross_file_io.dart | 15 ++++++ .../cross_file_io/lib/src/io_cross_file.dart | 40 ++++++++++++++++ .../cross_file/cross_file_io/pubspec.yaml | 48 ++++--------------- 4 files changed, 65 insertions(+), 45 deletions(-) diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 298576d81397..a540f8df62de 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -1,5 +1,2 @@ -/// A Calculator. -class Calculator { - /// Returns [value] plus 1. - int addOne(int value) => value + 1; -} + +c \ No newline at end of file diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index 8b137891791f..2c3cc5834d92 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -1 +1,16 @@ +// Platform Implementation for Android +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'io_cross_file.dart'; + +final class CrossFileIO extends CrossFilePlatform { + static void registerWith() { + CrossFilePlatform.instance = CrossFileIO(); + } + + @override + IOXFile createPlatformXFile(PlatformXFileCreationParams params) { + return IOXFile(params); + } +} diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 8b137891791f..61af921c9ed4 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -1 +1,41 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +base class IOXFile extends PlatformXFile with IOXFileExtension { + IOXFile(super.params) : super.implementation(); + + late final File file = File(params.path); + + @override + PlatformXFileExtension? get extension => this; + + @override + Future lastModified() => file.lastModified(); + + @override + Future length() => file.length(); + + @override + Stream> openRead([int? start, int? end]) => + file.openRead(start, end); + + @override + Future readAsBytes() => file.readAsBytes(); + + @override + Future readAsString({Encoding encoding = utf8}) => + file.readAsString(encoding: encoding); + + @override + Future canRead() => exists(); + + @override + Future exists() => file.exists(); +} + +mixin IOXFileExtension implements PlatformXFileExtension { + File get file; +} diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index ada4dc667f15..b4bb35e1060f 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -1,54 +1,22 @@ name: cross_file_io -description: "A new Flutter package project." +description: Something something darkside +repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 version: 0.0.1 -homepage: +publish_to: none environment: - sdk: ^3.11.0-146.0.dev - flutter: ">=1.17.0" + sdk: ^3.9.0 + flutter: ">=3.35.0" dependencies: flutter: sdk: flutter + cross_file_platform_interface: + path: ../cross_file_platform_interface dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^6.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # To add assets to your package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # To add custom fonts to your package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/to/font-from-package From 6aa3319f058560c82e0198e328b2ca83fcc40c00 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:53:03 -0500 Subject: [PATCH 029/398] initial web commit --- packages/cross_file/cross_file_web/.gitignore | 33 +++++++ packages/cross_file/cross_file_web/.metadata | 30 +++++++ .../cross_file/cross_file_web/CHANGELOG.md | 3 + packages/cross_file/cross_file_web/LICENSE | 1 + packages/cross_file/cross_file_web/README.md | 15 ++++ .../cross_file_web/analysis_options.yaml | 4 + .../cross_file_web/example/.gitignore | 45 ++++++++++ .../cross_file_web/example/README.md | 17 ++++ .../example/analysis_options.yaml | 28 ++++++ .../plugin_integration_test.dart | 24 +++++ .../cross_file_web/example/lib/main.dart | 59 ++++++++++++ .../cross_file_web/example/pubspec.yaml | 85 ++++++++++++++++++ .../example/test/widget_test.dart | 27 ++++++ .../cross_file_web/example/web/favicon.png | Bin 0 -> 917 bytes .../example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../example/web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes .../example/web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes .../cross_file_web/example/web/index.html | 46 ++++++++++ .../cross_file_web/example/web/manifest.json | 35 ++++++++ .../cross_file_web/lib/cross_file_web.dart | 8 ++ .../lib/cross_file_web_method_channel.dart | 19 ++++ .../cross_file_web_platform_interface.dart | 29 ++++++ .../lib/cross_file_web_web.dart | 26 ++++++ .../cross_file/cross_file_web/pubspec.yaml | 73 +++++++++++++++ .../cross_file_web_method_channel_test.dart | 26 ++++++ .../test/cross_file_web_test.dart | 28 ++++++ 27 files changed, 661 insertions(+) create mode 100644 packages/cross_file/cross_file_web/.gitignore create mode 100644 packages/cross_file/cross_file_web/.metadata create mode 100644 packages/cross_file/cross_file_web/CHANGELOG.md create mode 100644 packages/cross_file/cross_file_web/LICENSE create mode 100644 packages/cross_file/cross_file_web/README.md create mode 100644 packages/cross_file/cross_file_web/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_web/example/.gitignore create mode 100644 packages/cross_file/cross_file_web/example/README.md create mode 100644 packages/cross_file/cross_file_web/example/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart create mode 100644 packages/cross_file/cross_file_web/example/lib/main.dart create mode 100644 packages/cross_file/cross_file_web/example/pubspec.yaml create mode 100644 packages/cross_file/cross_file_web/example/test/widget_test.dart create mode 100644 packages/cross_file/cross_file_web/example/web/favicon.png create mode 100644 packages/cross_file/cross_file_web/example/web/icons/Icon-192.png create mode 100644 packages/cross_file/cross_file_web/example/web/icons/Icon-512.png create mode 100644 packages/cross_file/cross_file_web/example/web/icons/Icon-maskable-192.png create mode 100644 packages/cross_file/cross_file_web/example/web/icons/Icon-maskable-512.png create mode 100644 packages/cross_file/cross_file_web/example/web/index.html create mode 100644 packages/cross_file/cross_file_web/example/web/manifest.json create mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web.dart create mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart create mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart create mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web_web.dart create mode 100644 packages/cross_file/cross_file_web/pubspec.yaml create mode 100644 packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart create mode 100644 packages/cross_file/cross_file_web/test/cross_file_web_test.dart diff --git a/packages/cross_file/cross_file_web/.gitignore b/packages/cross_file/cross_file_web/.gitignore new file mode 100644 index 000000000000..b9d7f25b91b6 --- /dev/null +++ b/packages/cross_file/cross_file_web/.gitignore @@ -0,0 +1,33 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/packages/cross_file/cross_file_web/.metadata b/packages/cross_file/cross_file_web/.metadata new file mode 100644 index 000000000000..edd69034d058 --- /dev/null +++ b/packages/cross_file/cross_file_web/.metadata @@ -0,0 +1,30 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "7b98d50631e52399041060ae2ae19163cd5cba87" + channel: "main" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 + base_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 + - platform: web + create_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 + base_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_web/CHANGELOG.md b/packages/cross_file/cross_file_web/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/cross_file/cross_file_web/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_web/LICENSE b/packages/cross_file/cross_file_web/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/cross_file/cross_file_web/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md new file mode 100644 index 000000000000..a89013f88dc9 --- /dev/null +++ b/packages/cross_file/cross_file_web/README.md @@ -0,0 +1,15 @@ +# cross_file_web + +A new Flutter plugin project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/to/develop-plugins), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/packages/cross_file/cross_file_web/analysis_options.yaml b/packages/cross_file/cross_file_web/analysis_options.yaml new file mode 100644 index 000000000000..a5744c1cfbe7 --- /dev/null +++ b/packages/cross_file/cross_file_web/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_web/example/.gitignore b/packages/cross_file/cross_file_web/example/.gitignore new file mode 100644 index 000000000000..3820a95c65c3 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/cross_file/cross_file_web/example/README.md b/packages/cross_file/cross_file_web/example/README.md new file mode 100644 index 000000000000..a4d1dc0858ef --- /dev/null +++ b/packages/cross_file/cross_file_web/example/README.md @@ -0,0 +1,17 @@ +# cross_file_web_example + +Demonstrates how to use the cross_file_web plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) +- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/cross_file/cross_file_web/example/analysis_options.yaml b/packages/cross_file/cross_file_web/example/analysis_options.yaml new file mode 100644 index 000000000000..0d2902135cae --- /dev/null +++ b/packages/cross_file/cross_file_web/example/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart new file mode 100644 index 000000000000..bf7a4cd61995 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart @@ -0,0 +1,24 @@ +// This is a basic Flutter integration test. +// +// Since integration tests run in a full Flutter application, they can interact +// with the host side of a plugin implementation, unlike Dart unit tests. +// +// For more information about Flutter integration tests, please see +// https://flutter.dev/to/integration-testing + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:cross_file_web/cross_file_web.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getPlatformVersion test', (WidgetTester tester) async { + final CrossFileWeb plugin = CrossFileWeb(); + final String? version = await plugin.getPlatformVersion(); + // The version string depends on the host platform running the test, so + // just assert that some non-empty string is returned. + expect(version?.isNotEmpty, true); + }); +} diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart new file mode 100644 index 000000000000..99ec34c5a563 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:cross_file_web/cross_file_web.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + String _platformVersion = 'Unknown'; + final _crossFileWebPlugin = CrossFileWeb(); + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initPlatformState() async { + String platformVersion; + // Platform messages may fail, so we use a try/catch PlatformException. + // We also handle the message potentially returning null. + try { + platformVersion = + await _crossFileWebPlugin.getPlatformVersion() ?? 'Unknown platform version'; + } on PlatformException { + platformVersion = 'Failed to get platform version.'; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) return; + + setState(() { + _platformVersion = platformVersion; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar(title: const Text('Plugin example app')), + body: Center(child: Text('Running on: $_platformVersion\n')), + ), + ); + } +} diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml new file mode 100644 index 000000000000..44af8c0ae955 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -0,0 +1,85 @@ +name: cross_file_web_example +description: "Demonstrates how to use the cross_file_web plugin." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ^3.11.0-169.0.dev + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + cross_file_web: + # When depending on this package from a real application you should use: + # cross_file_web: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_web/example/test/widget_test.dart b/packages/cross_file/cross_file_web/example/test/widget_test.dart new file mode 100644 index 000000000000..538ffd75ff13 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cross_file_web_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/cross_file/cross_file_web/example/web/favicon.png b/packages/cross_file/cross_file_web/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_web/example/web/icons/Icon-192.png b/packages/cross_file/cross_file_web/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_web/example/web/icons/Icon-512.png b/packages/cross_file/cross_file_web/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_web/example/web/icons/Icon-maskable-192.png b/packages/cross_file/cross_file_web/example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_web/example/web/icons/Icon-maskable-512.png b/packages/cross_file/cross_file_web/example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_web/example/web/index.html b/packages/cross_file/cross_file_web/example/web/index.html new file mode 100644 index 000000000000..7f434f23cd1b --- /dev/null +++ b/packages/cross_file/cross_file_web/example/web/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + cross_file_web_example + + + + + + + diff --git a/packages/cross_file/cross_file_web/example/web/manifest.json b/packages/cross_file/cross_file_web/example/web/manifest.json new file mode 100644 index 000000000000..74f71b3a0ed8 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "cross_file_web_example", + "short_name": "cross_file_web_example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "Demonstrates how to use the cross_file_web plugin.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart new file mode 100644 index 000000000000..7ee8ee6a35b4 --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -0,0 +1,8 @@ + +import 'cross_file_web_platform_interface.dart'; + +class CrossFileWeb { + Future getPlatformVersion() { + return CrossFileWebPlatform.instance.getPlatformVersion(); + } +} diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart b/packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart new file mode 100644 index 000000000000..dfd276a4b201 --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart @@ -0,0 +1,19 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'cross_file_web_platform_interface.dart'; + +/// An implementation of [CrossFileWebPlatform] that uses method channels. +class MethodChannelCrossFileWeb extends CrossFileWebPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + final methodChannel = const MethodChannel('cross_file_web'); + + @override + Future getPlatformVersion() async { + final version = await methodChannel.invokeMethod( + 'getPlatformVersion', + ); + return version; + } +} diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart b/packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart new file mode 100644 index 000000000000..28142c8f9746 --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart @@ -0,0 +1,29 @@ +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'cross_file_web_method_channel.dart'; + +abstract class CrossFileWebPlatform extends PlatformInterface { + /// Constructs a CrossFileWebPlatform. + CrossFileWebPlatform() : super(token: _token); + + static final Object _token = Object(); + + static CrossFileWebPlatform _instance = MethodChannelCrossFileWeb(); + + /// The default instance of [CrossFileWebPlatform] to use. + /// + /// Defaults to [MethodChannelCrossFileWeb]. + static CrossFileWebPlatform get instance => _instance; + + /// Platform-specific implementations should set this with their own + /// platform-specific class that extends [CrossFileWebPlatform] when + /// they register themselves. + static set instance(CrossFileWebPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Future getPlatformVersion() { + throw UnimplementedError('platformVersion() has not been implemented.'); + } +} diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web_web.dart new file mode 100644 index 000000000000..b186d614e0f5 --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/cross_file_web_web.dart @@ -0,0 +1,26 @@ +// In order to *not* need this ignore, consider extracting the "web" version +// of your plugin as a separate package, instead of inlining it in the same +// package as the core of your plugin. +// ignore: avoid_web_libraries_in_flutter + +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; +import 'package:web/web.dart' as web; + +import 'cross_file_web_platform_interface.dart'; + +/// A web implementation of the CrossFileWebPlatform of the CrossFileWeb plugin. +class CrossFileWebWeb extends CrossFileWebPlatform { + /// Constructs a CrossFileWebWeb + CrossFileWebWeb(); + + static void registerWith(Registrar registrar) { + CrossFileWebPlatform.instance = CrossFileWebWeb(); + } + + /// Returns a [String] containing the version of the platform. + @override + Future getPlatformVersion() async { + final version = web.window.navigator.userAgent; + return version; + } +} diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml new file mode 100644 index 000000000000..41c542c264bf --- /dev/null +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -0,0 +1,73 @@ +name: cross_file_web +description: "A new Flutter plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.11.0-169.0.dev + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + flutter_web_plugins: + sdk: flutter + web: ^1.0.0 + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) + # which should be registered in the plugin registry. This is required for + # using method channels. + # The Android 'package' specifies package in which the registered class is. + # This is required for using method channels on Android. + # The 'ffiPlugin' specifies that native code should be built and bundled. + # This is required for using `dart:ffi`. + # All these are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + web: + pluginClass: CrossFileWebWeb + fileName: cross_file_web_web.dart + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart b/packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart new file mode 100644 index 000000000000..a1d82ae50459 --- /dev/null +++ b/packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart @@ -0,0 +1,26 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_web/cross_file_web_method_channel.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + MethodChannelCrossFileWeb platform = MethodChannelCrossFileWeb(); + const MethodChannel channel = MethodChannel('cross_file_web'); + + setUp(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + return '42'; + }); + }); + + tearDown(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, null); + }); + + test('getPlatformVersion', () async { + expect(await platform.getPlatformVersion(), '42'); + }); +} diff --git a/packages/cross_file/cross_file_web/test/cross_file_web_test.dart b/packages/cross_file/cross_file_web/test/cross_file_web_test.dart new file mode 100644 index 000000000000..58ce71b18e7f --- /dev/null +++ b/packages/cross_file/cross_file_web/test/cross_file_web_test.dart @@ -0,0 +1,28 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_web/cross_file_web.dart'; +import 'package:cross_file_web/cross_file_web_platform_interface.dart'; +import 'package:cross_file_web/cross_file_web_method_channel.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockCrossFileWebPlatform + with MockPlatformInterfaceMixin + implements CrossFileWebPlatform { + @override + Future getPlatformVersion() => Future.value('42'); +} + +void main() { + final CrossFileWebPlatform initialPlatform = CrossFileWebPlatform.instance; + + test('$MethodChannelCrossFileWeb is the default instance', () { + expect(initialPlatform, isInstanceOf()); + }); + + test('getPlatformVersion', () async { + CrossFileWeb crossFileWebPlugin = CrossFileWeb(); + MockCrossFileWebPlatform fakePlatform = MockCrossFileWebPlatform(); + CrossFileWebPlatform.instance = fakePlatform; + + expect(await crossFileWebPlugin.getPlatformVersion(), '42'); + }); +} From dfca2089407a0c516a4aee65f5b6c223563551c4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:23:25 -0500 Subject: [PATCH 030/398] web impl --- .../cross_file_web/lib/cross_file_web.dart | 10 +- .../lib/cross_file_web_method_channel.dart | 19 ---- .../cross_file_web_platform_interface.dart | 29 ----- .../lib/cross_file_web_web.dart | 26 ----- .../lib/src/cross_file_web.dart | 14 +++ .../lib/src/web_cross_file.dart | 100 +++++++++++++++++ .../cross_file_web/lib/src/web_helpers.dart | 102 ++++++++++++++++++ .../cross_file/cross_file_web/pubspec.yaml | 79 ++++---------- 8 files changed, 239 insertions(+), 140 deletions(-) delete mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart delete mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart delete mode 100644 packages/cross_file/cross_file_web/lib/cross_file_web_web.dart create mode 100644 packages/cross_file/cross_file_web/lib/src/cross_file_web.dart create mode 100644 packages/cross_file/cross_file_web/lib/src/web_cross_file.dart create mode 100644 packages/cross_file/cross_file_web/lib/src/web_helpers.dart diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 7ee8ee6a35b4..5a10e7aa04ff 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -1,8 +1,2 @@ - -import 'cross_file_web_platform_interface.dart'; - -class CrossFileWeb { - Future getPlatformVersion() { - return CrossFileWebPlatform.instance.getPlatformVersion(); - } -} +export 'src/web_cross_file.dart' show WebXFileExtension, WebXFileCreationParams; +export 'src/cross_file_web.dart'; diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart b/packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart deleted file mode 100644 index dfd276a4b201..000000000000 --- a/packages/cross_file/cross_file_web/lib/cross_file_web_method_channel.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -import 'cross_file_web_platform_interface.dart'; - -/// An implementation of [CrossFileWebPlatform] that uses method channels. -class MethodChannelCrossFileWeb extends CrossFileWebPlatform { - /// The method channel used to interact with the native platform. - @visibleForTesting - final methodChannel = const MethodChannel('cross_file_web'); - - @override - Future getPlatformVersion() async { - final version = await methodChannel.invokeMethod( - 'getPlatformVersion', - ); - return version; - } -} diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart b/packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart deleted file mode 100644 index 28142c8f9746..000000000000 --- a/packages/cross_file/cross_file_web/lib/cross_file_web_platform_interface.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -import 'cross_file_web_method_channel.dart'; - -abstract class CrossFileWebPlatform extends PlatformInterface { - /// Constructs a CrossFileWebPlatform. - CrossFileWebPlatform() : super(token: _token); - - static final Object _token = Object(); - - static CrossFileWebPlatform _instance = MethodChannelCrossFileWeb(); - - /// The default instance of [CrossFileWebPlatform] to use. - /// - /// Defaults to [MethodChannelCrossFileWeb]. - static CrossFileWebPlatform get instance => _instance; - - /// Platform-specific implementations should set this with their own - /// platform-specific class that extends [CrossFileWebPlatform] when - /// they register themselves. - static set instance(CrossFileWebPlatform instance) { - PlatformInterface.verifyToken(instance, _token); - _instance = instance; - } - - Future getPlatformVersion() { - throw UnimplementedError('platformVersion() has not been implemented.'); - } -} diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web_web.dart deleted file mode 100644 index b186d614e0f5..000000000000 --- a/packages/cross_file/cross_file_web/lib/cross_file_web_web.dart +++ /dev/null @@ -1,26 +0,0 @@ -// In order to *not* need this ignore, consider extracting the "web" version -// of your plugin as a separate package, instead of inlining it in the same -// package as the core of your plugin. -// ignore: avoid_web_libraries_in_flutter - -import 'package:flutter_web_plugins/flutter_web_plugins.dart'; -import 'package:web/web.dart' as web; - -import 'cross_file_web_platform_interface.dart'; - -/// A web implementation of the CrossFileWebPlatform of the CrossFileWeb plugin. -class CrossFileWebWeb extends CrossFileWebPlatform { - /// Constructs a CrossFileWebWeb - CrossFileWebWeb(); - - static void registerWith(Registrar registrar) { - CrossFileWebPlatform.instance = CrossFileWebWeb(); - } - - /// Returns a [String] containing the version of the platform. - @override - Future getPlatformVersion() async { - final version = web.window.navigator.userAgent; - return version; - } -} diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart new file mode 100644 index 000000000000..4951f10600ea --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -0,0 +1,14 @@ +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'web_cross_file.dart'; + +base class CrossFileWeb extends CrossFilePlatform { + static void registerWith() { + CrossFilePlatform.instance = CrossFileWeb(); + } + + @override + WebXFile createPlatformXFile(PlatformXFileCreationParams params) { + return WebXFile(params); + } +} diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart new file mode 100644 index 000000000000..6673a5209476 --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -0,0 +1,100 @@ +import 'dart:convert'; + +import 'dart:typed_data'; + +import 'package:web/web.dart'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'web_helpers.dart'; + +base class WebXFileCreationParams extends PlatformXFileCreationParams { + WebXFileCreationParams({required super.path, this.blob}); + + final Blob? blob; +} + +base class WebXFile extends PlatformXFile with WebXFileExtension { + WebXFile(super.params) : super.implementation(); + + Blob? _cachedBlob; + final DateTime defaultLastModified = DateTime.now(); + + @override + PlatformXFileExtension? get extension => this; + + @override + late final WebXFileCreationParams params = + super.params is WebXFileCreationParams + ? super.params as WebXFileCreationParams + : WebXFileCreationParams(path: params.path); + + Future getBlob() async { + return _cachedBlob ??= params.blob ?? await fetchBlob(params.path); + } + + @override + Future canRead() => exists(); + + @override + Future exists() async { + try { + await getBlob(); + return true; + } catch (exception) { + return false; + } + } + + @override + Future lastModified() async { + final Blob blob = await getBlob(); + if (blob is File) { + return DateTime.fromMillisecondsSinceEpoch(blob.lastModified); + } + + return defaultLastModified; + } + + @override + Future length() async { + return (await getBlob()).size; + } + + @override + Stream> openRead([int? start, int? end]) async* { + final Blob blob = await getBlob(); + final Blob slice = blob.slice(start ?? 0, end ?? blob.size, blob.type); + yield await blobToBytes(slice); + } + + @override + Future readAsBytes() async { + return blobToBytes(await getBlob()); + } + + @override + Future readAsString({Encoding encoding = utf8}) async { + return encoding.decode(await readAsBytes()); + } + + @override + Future download([String? suggestedName]) async { + final Blob blob = await getBlob(); + + String? name; + if (suggestedName != null) { + name = suggestedName; + } else if (blob is File) { + name = blob.name; + } + + await downloadBlob(blob, name); + } +} + +mixin WebXFileExtension implements PlatformXFileExtension { + Future getBlob(); + + Future download([String? suggestedName]); +} diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart new file mode 100644 index 000000000000..b967f3b9a173 --- /dev/null +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -0,0 +1,102 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:js_interop'; +import 'dart:typed_data'; + +import 'package:web/web.dart'; + +/// Create anchor element with download attribute +HTMLAnchorElement createAnchorElement(String href, String? suggestedName) => + (document.createElement('a') as HTMLAnchorElement) + ..href = href + ..download = suggestedName ?? 'download' + ..rel = 'noreferrer'; + +/// Add an element to a container and click it +void addElementToContainerAndClick(Element container, HTMLElement element) { + // Add the element and click it + // All previous elements will be removed before adding the new one + container.appendChild(element); + element.click(); +} + +/// Initializes a DOM container where elements can be injected. +Element ensureInitialized(String id) { + Element? target = document.querySelector('#$id'); + if (target == null) { + final Element targetElement = document.createElement('flt-x-file')..id = id; + + document.body!.appendChild(targetElement); + target = targetElement; + } + return target; +} + +/// Attempts to download an object (a [Blob]) from its [objectUrl], suggesting [name] as the filename. +/// +/// [name] is a mere *suggestion* for the saved filename; users usually can rename +/// the file to whatever they want before it's actually saved. +/// +/// Maybe some day: https://developer.mozilla.org/en-US/docs/Web/API/Window/showSaveFilePicker +void downloadObjectUrl(String objectUrl, String? name) { + // Create a DOM container where the anchor can be injected. + final Element target = ensureInitialized('__x_file_dom_element'); + // Create an tag with the appropriate download attributes and click it + final HTMLAnchorElement element = createAnchorElement(objectUrl, name); + // Clear the children in target. + target.replaceChildren(JSArray()); + // Add the new `element` and click. + addElementToContainerAndClick(target, element); +} + +/// Attempts to download a [blob], suggesting [name] as the filename. +/// +/// This method creates (and attempts to cleanup) an `objectUrl` for the given +/// [blob]. Since there's no way to know when the cleanup needs to happen, the +/// `blob` will seem to "leak" for about 5 minutes, until the `objectUrl` created +/// by this method is actually cleared. +Future downloadBlob(Blob blob, String? name) async { + final String objectUrl = URL.createObjectURL(blob); + // TODO(dit): Is there a better way to revoke the URL that we're creating? + Future.delayed(const Duration(minutes: 5), () { + // Is this the industry standard? + // See: https://github.com/eligrey/FileSaver.js/blob/cea522bc41bfadc364837293d0c4dc585a65ac46/src/FileSaver.js#L163 + URL.revokeObjectURL(objectUrl); + }); + downloadObjectUrl(objectUrl, name); +} + +/// Converts a [Blob] to [Uint8List] through a [FileReader]. +Future blobToBytes(Blob blob) async { + final FileReader reader = FileReader(); + reader.readAsArrayBuffer(blob); + await reader.onLoadEnd.first; + + final Uint8List? result = + (reader.result as JSArrayBuffer?)?.toDart.asUint8List(); + if (result == null) { + throw Exception('Cannot read bytes from Blob. Is it still available?'); + } + + return result; +} + +/// Converts a bunch of [bytes] into a [Blob] and an optional [mimeType]. +Blob bytesToBlob(Uint8List bytes, String? mimeType) { + return Blob( + [bytes.toJS].toJS, + BlobPropertyBag(type: mimeType ?? ''), + ); +} + +/// Retrieves a [Blob] by its [objectUrl]. +Future fetchBlob(String objectUrl) async { + try { + final Response response = await window.fetch(objectUrl.toJS).toDart; + return response.blob().toDart; + } catch (e) { + throw Exception('Could not fetch Blob by URL: $objectUrl'); + } +} \ No newline at end of file diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 41c542c264bf..5d00a548afd6 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -1,73 +1,36 @@ name: cross_file_web -description: "A new Flutter plugin project." +description: A Flutter plugin that provides a WebView widget on web. +repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_web +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 version: 0.0.1 -homepage: +publish_to: none environment: - sdk: ^3.11.0-169.0.dev - flutter: '>=3.3.0' + sdk: ^3.8.0 + flutter: ">=3.32.0" + +flutter: + plugin: + implements: cross_file + platforms: + web: + pluginClass: CrossFileWeb + fileName: cross_file_web.dart dependencies: flutter: sdk: flutter flutter_web_plugins: sdk: flutter - web: ^1.0.0 - plugin_platform_interface: ^2.0.2 + web: ">=0.5.1 <2.0.0" + cross_file_platform_interface: + path: ../cross_file_platform_interface dev_dependencies: + build_runner: ^2.1.5 flutter_test: sdk: flutter - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - # This section identifies this Flutter project as a plugin project. - # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) - # which should be registered in the plugin registry. This is required for - # using method channels. - # The Android 'package' specifies package in which the registered class is. - # This is required for using method channels on Android. - # The 'ffiPlugin' specifies that native code should be built and bundled. - # This is required for using `dart:ffi`. - # All these are used by the tooling to maintain consistency when - # adding or updating assets for this project. - plugin: - platforms: - web: - pluginClass: CrossFileWebWeb - fileName: cross_file_web_web.dart - - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images + mockito: ^5.4.4 - # To add custom fonts to your plugin package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/to/font-from-package +topics: + - file \ No newline at end of file From de3b931f88a7ad747175d299b122ff9dd52b1479 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 11 Dec 2025 12:24:36 -0500 Subject: [PATCH 031/398] docs for platform x file --- .../lib/src/shared_storage_cross_file.dart | 2 - .../lib/src/platform_cross_file.dart | 93 +++++++++++++++++-- 2 files changed, 86 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart index fa951368a4d6..64f1b5b445df 100644 --- a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart @@ -1,5 +1,3 @@ -import 'dart:convert'; -import 'dart:typed_data'; import 'package:flutter/foundation.dart' show immutable; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 34e105b00299..5f806ac247e5 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -1,25 +1,83 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'cross_file_platform.dart'; +/// Object specifying creation parameters for creating a [PlatformXFile]. +/// +/// Platform specific implementations can add additional fields by extending +/// this class. +/// +/// This example demonstrates how to extend the [PlatformXFileCreationParams] to +/// provide additional platform specific parameters. +/// +/// When extending [PlatformXFileCreationParams] additional parameters +/// should always accept `null` or have a default value to prevent breaking +/// changes. +/// +/// ```dart +/// base class AndroidPlatformXFileCreationParams +/// extends PlatformXFileCreationParams { +/// AndroidPlatformXFileCreationParams({required super.uri, this.platformValue}); +/// +/// factory AndroidPlatformXFileCreationParams.fromPlatformCreationParams( +/// PlatformXFileCreationParams params, { +/// Object? platformValue, +/// }) { +/// return AndroidPlatformXFileCreationParams( +/// uri: params.uri, +/// platformValue: platformValue, +/// ); +/// } +/// +/// final Object? platformValue; +/// } +/// ``` @immutable base class PlatformXFileCreationParams { - const PlatformXFileCreationParams({required this.path}); + /// Constructs a [PlatformXFileCreationParams]. + const PlatformXFileCreationParams({required this.uri}); - final String path; + /// A string used to reference the resource's location. + final String uri; } +/// Base mixin used to provide platform specific features for implementations of +/// [PlatformXFile]. +/// +/// Platform implementations are expected to declare a mixin that implements +/// this mixin and return an instance with [PlatformXFile.extension]. +/// +/// ```dart +/// base class AndroidPlatformXFile extends PlatformXFile with AndroidXFileExtension { +/// // ... +/// @override +/// PlatformXFileExtension? get extension => this; +/// +/// Future platformMethod() { +/// // ... +/// } +/// } +/// +/// mixin AndroidXFileExtension implements PlatformXFileExtension { +/// Future platformMethod(); +/// } +/// ``` mixin PlatformXFileExtension {} +/// Interface for a reference to a local data resource. abstract base class PlatformXFile { /// Creates a new [PlatformXFile] factory PlatformXFile(PlatformXFileCreationParams params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' - 'ensure that an implementation of `XFilePlatform` has been set to ' + 'ensure that an implementation of `CrossFilePlatform` has been set to ' '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); @@ -29,28 +87,49 @@ abstract base class PlatformXFile { return file; } + /// Used by the platform implementation to create a new [PlatformXFile]. + /// + /// Should only be used by platform implementations because they can't extend + /// a class that only contains a factory constructor. @protected PlatformXFile.implementation(this.params); + /// The parameters used to initialize the [PlatformXFile]. final PlatformXFileCreationParams params; + /// Extension for providing platform specific features. PlatformXFileExtension? get extension => null; + /// Date and time when the resource was last modified, if the information is + /// available. + /// + /// Platforms may throw an exception if the information is not available. Future lastModified(); - /// The length of the file. + /// The length of the data represented by this uri, in bytes. Future length(); - /// Whether file exists. + /// Whether the resource represented by this reference exists. Future exists(); + /// Whether the resource represented by this reference can be read. Future canRead(); + /// Creates a new independent Stream for the contents of this resource. + /// + /// If start is present, the file will be read from byte-offset start. + /// Otherwise from the beginning (index 0). + /// + /// If end is present, only bytes up to byte-index end will be read. + /// Otherwise, until end of file. + /// + /// Platforms can throw an exception if there is an error opening or reading + /// the resource. Stream> openRead([int? start, int? end]); - /// Reads the entire file contents as a list of bytes. + /// Reads the entire resource contents as a list of bytes. Future readAsBytes(); - /// Reads the entire file contents as a string using the given Encoding. + /// Reads the entire resource contents as a string using the given Encoding. Future readAsString({Encoding encoding = utf8}); } From ca99adac35c1e8ec16674cccd290a56d4720b648 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 11 Dec 2025 13:27:39 -0500 Subject: [PATCH 032/398] some stuff done --- .../lib/src/cross_file_platform.dart | 13 +++ .../lib/src/platform_cross_directory.dart | 81 +++++++++++++++++-- .../lib/src/platform_cross_file.dart | 10 +-- .../lib/src/platform_cross_file_entity.dart | 10 +++ ...atform_shared_storage_cross_directory.dart | 4 + .../platform_shared_storage_cross_file.dart | 77 +++++++++++++++--- 6 files changed, 172 insertions(+), 23 deletions(-) create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index d57c2e39d612..b2bb383f6fac 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -1,5 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'platform_cross_directory.dart'; import 'platform_cross_file.dart'; +import 'shared_storage/platform_shared_storage_cross_directory.dart'; import 'shared_storage/platform_shared_storage_cross_file.dart'; abstract base class CrossFilePlatform { @@ -22,4 +27,12 @@ abstract base class CrossFilePlatform { 'createPlatformXDirectory is not implemented on the current platform.', ); } + + PlatformSharedStorageXDirectory createPlatformSharedStorageXDirectory( + PlatformSharedStorageXFileCreationParams params, + ) { + throw UnimplementedError( + 'createPlatformSharedStorageXDirectory is not implemented on the current platform.', + ); + } } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index c7452ba71656..db597940605d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -1,18 +1,78 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'package:flutter/foundation.dart'; +import '../cross_file_platform_interface.dart'; +import 'platform_cross_file_entity.dart'; import 'cross_file_platform.dart'; +/// Object specifying creation parameters for creating a [PlatformXDirectory]. +/// +/// Platform specific implementations can add additional fields by extending +/// this class. +/// +/// This example demonstrates how to extend the [PlatformXDirectoryCreationParams] to +/// provide additional platform specific parameters. +/// +/// When extending [PlatformXDirectoryCreationParams] additional parameters +/// should always accept `null` or have a default value to prevent breaking +/// changes. +/// +/// ```dart +/// base class AndroidPlatformXDirectoryCreationParams +/// extends PlatformXDirectoryCreationParams { +/// AndroidPlatformXDirectoryCreationParams({required super.uri, this.platformValue}); +/// +/// factory AndroidPlatformXDirectoryCreationParams.fromCreationParams( +/// PlatformXDirectoryCreationParams params, { +/// Object? platformValue, +/// }) { +/// return AndroidPlatformXDirectoryCreationParams( +/// uri: params.uri, +/// platformValue: platformValue, +/// ); +/// } +/// +/// final Object? platformValue; +/// } +/// ``` @immutable base class PlatformXDirectoryCreationParams { - const PlatformXDirectoryCreationParams({required this.path}); + /// Constructs a [PlatformXDirectoryCreationParams]. + const PlatformXDirectoryCreationParams({required this.uri}); - final String path; + /// A string used to reference the resource's location. + final String uri; } +/// Base mixin used to provide platform specific features for implementations of +/// [PlatformXDirectory]. +/// +/// Platform implementations are expected to declare a mixin that implements +/// this mixin and return an instance with [PlatformXDirectory.extension]. +/// +/// ```dart +/// base class AndroidPlatformXDirectory extends PlatformXDirectory with AndroidXFileExtension { +/// // ... +/// @override +/// PlatformXDirectoryExtension? get extension => this; +/// +/// Future platformMethod() { +/// // ... +/// } +/// } +/// +/// mixin AndroidXFileExtension implements PlatformXDirectoryExtension { +/// Future platformMethod(); +/// } +/// ``` mixin PlatformXDirectoryExtension {} -abstract base class PlatformXDirectory { - /// Creates a new [PlatformXDirectory] +/// A reference to a directory (or folder) on the file system. +abstract base class PlatformXDirectory implements PlatformCrossFileEntity { + /// Creates a new [PlatformXDirectory]. factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { assert( CrossFilePlatform.instance != null, @@ -26,12 +86,23 @@ abstract base class PlatformXDirectory { return file; } + /// Used by the platform implementation to create a new [PlatformXDirectory]. + /// + /// Should only be used by platform implementations because they can't extend + /// a class that only contains a factory constructor. @protected PlatformXDirectory.implementation(this.params); + /// The parameters used to initialize the [PlatformXDirectory]. final PlatformXDirectoryCreationParams params; + /// Extension for providing platform specific features. PlatformXDirectoryExtension? get extension => null; - Future exists(); + /// Lists the sub-directories and files of this Directory. + Future> list(ListParams params); +} + +class ListParams { + } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 5f806ac247e5..756bdbe9cc6d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'cross_file_platform.dart'; +import 'platform_cross_file_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXFile]. /// @@ -25,7 +26,7 @@ import 'cross_file_platform.dart'; /// extends PlatformXFileCreationParams { /// AndroidPlatformXFileCreationParams({required super.uri, this.platformValue}); /// -/// factory AndroidPlatformXFileCreationParams.fromPlatformCreationParams( +/// factory AndroidPlatformXFileCreationParams.fromCreationParams( /// PlatformXFileCreationParams params, { /// Object? platformValue, /// }) { @@ -71,8 +72,8 @@ base class PlatformXFileCreationParams { mixin PlatformXFileExtension {} /// Interface for a reference to a local data resource. -abstract base class PlatformXFile { - /// Creates a new [PlatformXFile] +abstract base class PlatformXFile implements PlatformCrossFileEntity { + /// Creates a new [PlatformXFile]. factory PlatformXFile(PlatformXFileCreationParams params) { assert( CrossFilePlatform.instance != null, @@ -109,9 +110,6 @@ abstract base class PlatformXFile { /// The length of the data represented by this uri, in bytes. Future length(); - /// Whether the resource represented by this reference exists. - Future exists(); - /// Whether the resource represented by this reference can be read. Future canRead(); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart new file mode 100644 index 000000000000..e6de453a29ca --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + + +abstract interface class PlatformCrossFileEntity { + /// Whether the resource represented by this reference exists. + Future exists(); +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart index d77542ae9f94..66a13475483d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'package:flutter/foundation.dart'; import '../../cross_file_platform_interface.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart index f63cb6f20c64..ac3158767e7b 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart @@ -1,16 +1,69 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'package:flutter/foundation.dart'; import '../../cross_file_platform_interface.dart'; -// TODO: difference between path and tostring -// TODO: Absolute string definition: "Returns true if this URI is absolute, i.e. if it contains an explicit scheme." -// TODO: it is relative if not +/// Object specifying creation parameters for creating a [PlatformXFile]. +/// +/// Platform specific implementations can add additional fields by extending +/// this class. +/// +/// This example demonstrates how to extend the [PlatformXFileCreationParams] to +/// provide additional platform specific parameters. +/// +/// When extending [PlatformXFileCreationParams] additional parameters +/// should always accept `null` or have a default value to prevent breaking +/// changes. +/// +/// ```dart +/// base class AndroidPlatformXFileCreationParams +/// extends PlatformXFileCreationParams { +/// AndroidPlatformXFileCreationParams({required super.uri, this.platformValue}); +/// +/// factory AndroidPlatformXFileCreationParams.fromCreationParams( +/// PlatformXFileCreationParams params, { +/// Object? platformValue, +/// }) { +/// return AndroidPlatformXFileCreationParams( +/// uri: params.uri, +/// platformValue: platformValue, +/// ); +/// } +/// +/// final Object? platformValue; +/// } +/// ``` @immutable base class PlatformSharedStorageXFileCreationParams extends PlatformXFileCreationParams { - const PlatformSharedStorageXFileCreationParams({required super.path}); + /// Constructs a [PlatformXFileCreationParams]. + const PlatformSharedStorageXFileCreationParams({required super.uri}); } +/// Base mixin used to provide platform specific features for implementations of +/// [PlatformXFile]. +/// +/// Platform implementations are expected to declare a mixin that implements +/// this mixin and return an instance with [PlatformXFile.extension]. +/// +/// ```dart +/// base class AndroidPlatformXFile extends PlatformXFile with AndroidXFileExtension { +/// // ... +/// @override +/// PlatformXFileExtension? get extension => this; +/// +/// Future platformMethod() { +/// // ... +/// } +/// } +/// +/// mixin AndroidXFileExtension implements PlatformXFileExtension { +/// Future platformMethod(); +/// } +/// ``` mixin SharedStoragePlatformXFileExtension implements PlatformXFileExtension {} abstract base class PlatformSharedStorageXFile extends PlatformXFile { @@ -30,21 +83,21 @@ abstract base class PlatformSharedStorageXFile extends PlatformXFile { return file; } + /// Used by the platform implementation to create a new [PlatformXFile]. + /// + /// Should only be used by platform implementations because they can't extend + /// a class that only contains a factory constructor. @protected - PlatformSharedStorageXFile.implementation(PlatformSharedStorageXFileCreationParams params) - : super.implementation(params); + PlatformSharedStorageXFile.implementation(super.params) + : super.implementation(); + /// The parameters used to initialize the [PlatformXFile]. @override PlatformSharedStorageXFileCreationParams get params => super.params as PlatformSharedStorageXFileCreationParams; + /// Extension for providing platform specific features. @override SharedStoragePlatformXFileExtension? get extension => super.extension as SharedStoragePlatformXFileExtension?; - - Future delete(); - - Future absoluteString() { - throw UnimplementedError(); - } } From 0984f9aef1c589cdb5496a600c494c5a4f5d8019 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:25:32 -0500 Subject: [PATCH 033/398] some work --- .../lib/cross_file_platform_interface.dart | 5 +++++ .../lib/src/platform_cross_file.dart | 15 +++++++-------- .../lib/src/platform_cross_file_entity.dart | 18 +++++++++++++++++- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index 8bc4460ed05d..fd432c898a44 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -1,4 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'src/cross_file_platform.dart'; export 'src/platform_cross_directory.dart'; export 'src/platform_cross_file.dart'; +export 'src/platform_cross_file_entity.dart'; export 'src/shared_storage/platform_shared_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 756bdbe9cc6d..f5258e33a827 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -40,12 +40,9 @@ import 'platform_cross_file_entity.dart'; /// } /// ``` @immutable -base class PlatformXFileCreationParams { +base class PlatformXFileCreationParams extends PlatformCrossFileEntityCreationParams { /// Constructs a [PlatformXFileCreationParams]. - const PlatformXFileCreationParams({required this.uri}); - - /// A string used to reference the resource's location. - final String uri; + const PlatformXFileCreationParams({required super.uri}); } /// Base mixin used to provide platform specific features for implementations of @@ -72,7 +69,7 @@ base class PlatformXFileCreationParams { mixin PlatformXFileExtension {} /// Interface for a reference to a local data resource. -abstract base class PlatformXFile implements PlatformCrossFileEntity { +abstract base class PlatformXFile extends PlatformCrossFileEntity { /// Creates a new [PlatformXFile]. factory PlatformXFile(PlatformXFileCreationParams params) { assert( @@ -93,10 +90,12 @@ abstract base class PlatformXFile implements PlatformCrossFileEntity { /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformXFile.implementation(this.params); + PlatformXFile.implementation(super.params); /// The parameters used to initialize the [PlatformXFile]. - final PlatformXFileCreationParams params; + @override + PlatformXFileCreationParams get params => + super.params as PlatformXFileCreationParams; /// Extension for providing platform specific features. PlatformXFileExtension? get extension => null; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart index e6de453a29ca..a8c68952d900 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart @@ -2,9 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/foundation.dart'; +/// +@immutable +abstract base class PlatformCrossFileEntityCreationParams { + /// Constructs a [PlatformXFileCreationParams]. + const PlatformCrossFileEntityCreationParams({required this.uri}); + + /// A string used to reference the resource's location. + final String uri; +} + + +abstract base class PlatformCrossFileEntity { + PlatformCrossFileEntity(this.params); + + /// The parameters used to initialize the [PlatformCrossFileEntity]. + final PlatformCrossFileEntityCreationParams params; -abstract interface class PlatformCrossFileEntity { /// Whether the resource represented by this reference exists. Future exists(); } From 60d8e6c3340a0289a8bcab98a29e19afa33d17ac Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 13 Dec 2025 17:57:40 -0500 Subject: [PATCH 034/398] new_crossfile --- .../lib/cross_file_platform_interface.dart | 1 + .../lib/src/cross_file_platform.dart | 35 ++++-- .../lib/src/platform_cross_directory.dart | 59 +++++----- .../lib/src/platform_cross_file.dart | 46 ++++---- .../lib/src/platform_cross_file_entity.dart | 26 +++-- ...atform_shared_storage_cross_directory.dart | 102 ++++++++++++++---- .../platform_shared_storage_cross_file.dart | 64 ++++++----- 7 files changed, 215 insertions(+), 118 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index fd432c898a44..c825aff5fbd4 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -6,4 +6,5 @@ export 'src/cross_file_platform.dart'; export 'src/platform_cross_directory.dart'; export 'src/platform_cross_file.dart'; export 'src/platform_cross_file_entity.dart'; +export 'src/shared_storage/platform_shared_storage_cross_directory.dart'; export 'src/shared_storage/platform_shared_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index b2bb383f6fac..367a17546a92 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -2,34 +2,51 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/foundation.dart'; + import 'platform_cross_directory.dart'; import 'platform_cross_file.dart'; import 'shared_storage/platform_shared_storage_cross_directory.dart'; import 'shared_storage/platform_shared_storage_cross_file.dart'; +/// Interface for a platform implementation of `cross_file`. abstract base class CrossFilePlatform { + /// The instance of [CrossFilePlatform] to be used. + /// + /// Platform implementations packages should set this with their own + /// implementation of [CrossFilePlatform] when they register themselves. static CrossFilePlatform? instance; - PlatformXFile createPlatformXFile(PlatformXFileCreationParams params); + /// Creates a new [PlatformXFile]. + @optionalTypeArgs + PlatformXFile createPlatformXFile< + T extends PlatformXFileCreationParams, + S extends PlatformXFileExtension + >(PlatformXFileCreationParams params); - PlatformSharedStorageXFile createPlatformSharedStorageXFile( - PlatformSharedStorageXFileCreationParams params, - ) { + /// Creates a new [PlatformXDirectory]. + @optionalTypeArgs + PlatformXDirectory createPlatformXDirectory< + T extends PlatformXDirectoryCreationParams, + S extends PlatformXDirectoryExtension + >(PlatformXDirectoryCreationParams params) { throw UnimplementedError( - 'createPlatformSharedStorageXFile is not implemented on the current platform.', + 'createPlatformXDirectory is not implemented on the current platform.', ); } - PlatformXDirectory createPlatformXDirectory( - PlatformXDirectoryCreationParams params, + /// Creates a new [PlatformSharedStorageXDirectory]. + PlatformSharedStorageXFile createPlatformSharedStorageXFile( + PlatformSharedStorageXFileCreationParams params, ) { throw UnimplementedError( - 'createPlatformXDirectory is not implemented on the current platform.', + 'createPlatformSharedStorageXFile is not implemented on the current platform.', ); } + /// Creates a new [PlatformSharedStorageXDirectory]. PlatformSharedStorageXDirectory createPlatformSharedStorageXDirectory( - PlatformSharedStorageXFileCreationParams params, + PlatformSharedStorageXDirectoryCreationParams params, ) { throw UnimplementedError( 'createPlatformSharedStorageXDirectory is not implemented on the current platform.', diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index db597940605d..7490687435f7 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -2,11 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:flutter/foundation.dart'; -import '../cross_file_platform_interface.dart'; -import 'platform_cross_file_entity.dart'; import 'cross_file_platform.dart'; +import 'platform_cross_file_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXDirectory]. /// @@ -21,15 +22,15 @@ import 'cross_file_platform.dart'; /// changes. /// /// ```dart -/// base class AndroidPlatformXDirectoryCreationParams +/// base class AndroidXDirectoryCreationParams /// extends PlatformXDirectoryCreationParams { -/// AndroidPlatformXDirectoryCreationParams({required super.uri, this.platformValue}); +/// AndroidXDirectoryCreationParams({required super.uri, this.platformValue}); /// -/// factory AndroidPlatformXDirectoryCreationParams.fromCreationParams( +/// factory AndroidXDirectoryCreationParams.fromCreationParams( /// PlatformXDirectoryCreationParams params, { /// Object? platformValue, /// }) { -/// return AndroidPlatformXDirectoryCreationParams( +/// return AndroidXDirectoryCreationParams( /// uri: params.uri, /// platformValue: platformValue, /// ); @@ -39,12 +40,10 @@ import 'cross_file_platform.dart'; /// } /// ``` @immutable -base class PlatformXDirectoryCreationParams { +base class PlatformXDirectoryCreationParams + extends PlatformXFileEntityCreationParams { /// Constructs a [PlatformXDirectoryCreationParams]. - const PlatformXDirectoryCreationParams({required this.uri}); - - /// A string used to reference the resource's location. - final String uri; + const PlatformXDirectoryCreationParams({required super.uri}); } /// Base mixin used to provide platform specific features for implementations of @@ -54,7 +53,7 @@ base class PlatformXDirectoryCreationParams { /// this mixin and return an instance with [PlatformXDirectory.extension]. /// /// ```dart -/// base class AndroidPlatformXDirectory extends PlatformXDirectory with AndroidXFileExtension { +/// base class AndroidXDirectory extends PlatformXDirectory with AndroidXFileExtension { /// // ... /// @override /// PlatformXDirectoryExtension? get extension => this; @@ -68,12 +67,16 @@ base class PlatformXDirectoryCreationParams { /// Future platformMethod(); /// } /// ``` -mixin PlatformXDirectoryExtension {} +mixin PlatformXDirectoryExtension implements PlatformXFileEntityExtension {} /// A reference to a directory (or folder) on the file system. -abstract base class PlatformXDirectory implements PlatformCrossFileEntity { +abstract base class PlatformXDirectory< + T extends PlatformXDirectoryCreationParams, + S extends PlatformXDirectoryExtension +> + extends PlatformXFileEntity { /// Creates a new [PlatformXDirectory]. - factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { + factory PlatformXDirectory(T params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' @@ -81,9 +84,7 @@ abstract base class PlatformXDirectory implements PlatformCrossFileEntity { '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); - final PlatformXDirectory file = CrossFilePlatform.instance! - .createPlatformXDirectory(params); - return file; + return CrossFilePlatform.instance!.createPlatformXDirectory(params); } /// Used by the platform implementation to create a new [PlatformXDirectory]. @@ -91,18 +92,18 @@ abstract base class PlatformXDirectory implements PlatformCrossFileEntity { /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformXDirectory.implementation(this.params); - - /// The parameters used to initialize the [PlatformXDirectory]. - final PlatformXDirectoryCreationParams params; - - /// Extension for providing platform specific features. - PlatformXDirectoryExtension? get extension => null; + PlatformXDirectory.implementation(super.params); /// Lists the sub-directories and files of this Directory. - Future> list(ListParams params); + Stream< + PlatformXFileEntity< + PlatformXFileEntityCreationParams, + PlatformXFileEntityExtension + > + > + list(ListParams params); } -class ListParams { - -} +/// Base class for parameters passed to [PlatformXDirectory.list]. +@immutable +base class ListParams {} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index f5258e33a827..e52081f83b28 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -22,15 +22,15 @@ import 'platform_cross_file_entity.dart'; /// changes. /// /// ```dart -/// base class AndroidPlatformXFileCreationParams +/// base class AndroidXFileCreationParams /// extends PlatformXFileCreationParams { -/// AndroidPlatformXFileCreationParams({required super.uri, this.platformValue}); +/// AndroidXFileCreationParams({required super.uri, this.platformValue}); /// -/// factory AndroidPlatformXFileCreationParams.fromCreationParams( +/// factory AndroidXFileCreationParams.fromCreationParams( /// PlatformXFileCreationParams params, { /// Object? platformValue, /// }) { -/// return AndroidPlatformXFileCreationParams( +/// return AndroidXFileCreationParams( /// uri: params.uri, /// platformValue: platformValue, /// ); @@ -40,7 +40,8 @@ import 'platform_cross_file_entity.dart'; /// } /// ``` @immutable -base class PlatformXFileCreationParams extends PlatformCrossFileEntityCreationParams { +base class PlatformXFileCreationParams + extends PlatformXFileEntityCreationParams { /// Constructs a [PlatformXFileCreationParams]. const PlatformXFileCreationParams({required super.uri}); } @@ -52,7 +53,7 @@ base class PlatformXFileCreationParams extends PlatformCrossFileEntityCreationPa /// this mixin and return an instance with [PlatformXFile.extension]. /// /// ```dart -/// base class AndroidPlatformXFile extends PlatformXFile with AndroidXFileExtension { +/// base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { /// // ... /// @override /// PlatformXFileExtension? get extension => this; @@ -66,12 +67,16 @@ base class PlatformXFileCreationParams extends PlatformCrossFileEntityCreationPa /// Future platformMethod(); /// } /// ``` -mixin PlatformXFileExtension {} +mixin PlatformXFileExtension implements PlatformXFileEntityExtension {} /// Interface for a reference to a local data resource. -abstract base class PlatformXFile extends PlatformCrossFileEntity { +abstract base class PlatformXFile< + T extends PlatformXFileCreationParams, + S extends PlatformXFileExtension +> + extends PlatformXFileEntity { /// Creates a new [PlatformXFile]. - factory PlatformXFile(PlatformXFileCreationParams params) { + factory PlatformXFile(T params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' @@ -79,10 +84,7 @@ abstract base class PlatformXFile extends PlatformCrossFileEntity { '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); - final PlatformXFile file = CrossFilePlatform.instance!.createPlatformXFile( - params, - ); - return file; + return CrossFilePlatform.instance!.createPlatformXFile(params); } /// Used by the platform implementation to create a new [PlatformXFile]. @@ -92,14 +94,6 @@ abstract base class PlatformXFile extends PlatformCrossFileEntity { @protected PlatformXFile.implementation(super.params); - /// The parameters used to initialize the [PlatformXFile]. - @override - PlatformXFileCreationParams get params => - super.params as PlatformXFileCreationParams; - - /// Extension for providing platform specific features. - PlatformXFileExtension? get extension => null; - /// Date and time when the resource was last modified, if the information is /// available. /// @@ -107,6 +101,8 @@ abstract base class PlatformXFile extends PlatformCrossFileEntity { Future lastModified(); /// The length of the data represented by this uri, in bytes. + /// + /// Platforms may throw an exception if the information is not available. Future length(); /// Whether the resource represented by this reference can be read. @@ -120,13 +116,19 @@ abstract base class PlatformXFile extends PlatformCrossFileEntity { /// If end is present, only bytes up to byte-index end will be read. /// Otherwise, until end of file. /// - /// Platforms can throw an exception if there is an error opening or reading + /// Platforms may throw an exception if there is an error opening or reading /// the resource. Stream> openRead([int? start, int? end]); /// Reads the entire resource contents as a list of bytes. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. Future readAsBytes(); /// Reads the entire resource contents as a string using the given Encoding. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. Future readAsString({Encoding encoding = utf8}); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart index a8c68952d900..68f2407024e4 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart @@ -4,22 +4,34 @@ import 'package:flutter/foundation.dart'; -/// +/// The common superclass for [PlatformXFileCreationParams] and +/// [PlatformXDirectoryCreationParams]. @immutable -abstract base class PlatformCrossFileEntityCreationParams { +abstract base class PlatformXFileEntityCreationParams { /// Constructs a [PlatformXFileCreationParams]. - const PlatformCrossFileEntityCreationParams({required this.uri}); + const PlatformXFileEntityCreationParams({required this.uri}); /// A string used to reference the resource's location. final String uri; } +/// The common superclass for [PlatformXFileExtension] and +/// [PlatformXDirectoryExtension]. +mixin PlatformXFileEntityExtension {} -abstract base class PlatformCrossFileEntity { - PlatformCrossFileEntity(this.params); +/// The common superclass for [PlatformXFile] and [PlatformXDirectory]. +abstract base class PlatformXFileEntity< + T extends PlatformXFileEntityCreationParams, + S extends PlatformXFileEntityExtension +> { + /// Constructs a [PlatformCrossFileEntity]. + PlatformXFileEntity(this.params); - /// The parameters used to initialize the [PlatformCrossFileEntity]. - final PlatformCrossFileEntityCreationParams params; + /// The parameters used to initialize the [PlatformXFileEntity]. + final T params; + + /// Extension for providing platform specific features. + S? get extension => null; /// Whether the resource represented by this reference exists. Future exists(); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart index 66a13475483d..47b4bbc875b9 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart @@ -4,33 +4,99 @@ import 'package:flutter/foundation.dart'; -import '../../cross_file_platform_interface.dart'; +import '../cross_file_platform.dart'; +import '../platform_cross_directory.dart'; +/// Object specifying creation parameters for creating a [PlatformSharedStorageXDirectory]. +/// +/// Platform specific implementations can add additional fields by extending +/// this class. +/// +/// This example demonstrates how to extend the [PlatformSharedStorageXDirectoryCreationParams] to +/// provide additional platform specific parameters. +/// +/// When extending [PlatformSharedStorageXDirectoryCreationParams] additional parameters +/// should always accept `null` or have a default value to prevent breaking +/// changes. +/// +/// ```dart +/// base class AndroidSharedStorageXDirectoryCreationParams +/// extends PlatformSharedStorageXDirectoryCreationParams { +/// AndroidSharedStorageXDirectoryCreationParams({required super.uri, this.platformValue}); +/// +/// factory AndroidSharedStorageXDirectoryCreationParams.fromCreationParams( +/// PlatformSharedStorageXDirectoryCreationParams params, { +/// Object? platformValue, +/// }) { +/// return AndroidSharedStorageXDirectoryCreationParams( +/// uri: params.uri, +/// platformValue: platformValue, +/// ); +/// } +/// +/// final Object? platformValue; +/// } +/// ``` @immutable base class PlatformSharedStorageXDirectoryCreationParams extends PlatformXDirectoryCreationParams { - const PlatformSharedStorageXDirectoryCreationParams({required super.path}); + /// Constructs a [PlatformSharedStorageXDirectoryCreationParams]. + const PlatformSharedStorageXDirectoryCreationParams({required super.uri}); } +/// Base mixin used to provide platform specific features for implementations of +/// [PlatformSharedStorageXDirectory]. +/// +/// Platform implementations are expected to declare a mixin that implements +/// this mixin and return an instance with [PlatformSharedStorageXDirectory.extension]. +/// +/// ```dart +/// base class AndroidSharedStorageXDirectory extends PlatformSharedStorageXDirectory with AndroidXFileExtension { +/// // ... +/// @override +/// PlatformSharedStorageXDirectoryExtension? get extension => this; +/// +/// Future platformMethod() { +/// // ... +/// } +/// } +/// +/// mixin AndroidXFileExtension implements PlatformSharedStorageXDirectoryExtension { +/// Future platformMethod(); +/// } +/// ``` mixin SharedStoragePlatformXDirectoryExtension implements PlatformXDirectoryExtension {} -abstract base class PlatformSharedStorageXDirectory extends PlatformXDirectory { - PlatformSharedStorageXDirectory( +/// A reference to a directory (or folder) on the file system within a devices +/// shared storage. +abstract base class PlatformSharedStorageXDirectory + extends + PlatformXDirectory< + PlatformSharedStorageXDirectoryCreationParams, + SharedStoragePlatformXDirectoryExtension + > { + /// Creates a new [PlatformSharedStorageXDirectory] + factory PlatformSharedStorageXDirectory( PlatformSharedStorageXDirectoryCreationParams params, - ) : super.implementation(params); - - @override - PlatformSharedStorageXDirectoryCreationParams get params => - super.params as PlatformSharedStorageXDirectoryCreationParams; - - @override - SharedStoragePlatformXDirectoryExtension? get extension => - super.extension as SharedStoragePlatformXDirectoryExtension?; - - Future listFiles(ListFileParams params); -} - -class ListFileParams { + ) { + assert( + CrossFilePlatform.instance != null, + 'A platform implementation for `cross_file` has not been set. Please ' + 'ensure that an implementation of `CrossFilePlatform` has been set to ' + '`CrossFilePlatform.instance` before use. For unit testing, ' + '`CrossFilePlatform.instance` can be set with your own test implementation.', + ); + return CrossFilePlatform.instance!.createPlatformSharedStorageXDirectory( + params, + ); + } + /// Used by the platform implementation to create a new + /// [PlatformSharedStorageXDirectory]. + /// + /// Should only be used by platform implementations because they can't extend + /// a class that only contains a factory constructor. + PlatformSharedStorageXDirectory.implementation(super.params) + : super.implementation(); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart index ac3158767e7b..cb1793c398c3 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart @@ -4,30 +4,32 @@ import 'package:flutter/foundation.dart'; -import '../../cross_file_platform_interface.dart'; +import '../cross_file_platform.dart'; +import '../platform_cross_file.dart'; -/// Object specifying creation parameters for creating a [PlatformXFile]. + +/// Object specifying creation parameters for creating a [PlatformSharedStorageXFile]. /// /// Platform specific implementations can add additional fields by extending /// this class. /// -/// This example demonstrates how to extend the [PlatformXFileCreationParams] to +/// This example demonstrates how to extend the [PlatformSharedStorageXFileCreationParams] to /// provide additional platform specific parameters. /// -/// When extending [PlatformXFileCreationParams] additional parameters +/// When extending [PlatformSharedStorageXFileCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking /// changes. /// /// ```dart -/// base class AndroidPlatformXFileCreationParams -/// extends PlatformXFileCreationParams { -/// AndroidPlatformXFileCreationParams({required super.uri, this.platformValue}); +/// base class AndroidSharedStorageXFileCreationParams +/// extends PlatformSharedStorageXFileCreationParams { +/// AndroidSharedStorageXFileCreationParams({required super.uri, this.platformValue}); /// -/// factory AndroidPlatformXFileCreationParams.fromCreationParams( -/// PlatformXFileCreationParams params, { +/// factory AndroidSharedStorageXFileCreationParams.fromCreationParams( +/// PlatformSharedStorageXFileCreationParams params, { /// Object? platformValue, /// }) { -/// return AndroidPlatformXFileCreationParams( +/// return AndroidSharedStorageXFileCreationParams( /// uri: params.uri, /// platformValue: platformValue, /// ); @@ -39,34 +41,41 @@ import '../../cross_file_platform_interface.dart'; @immutable base class PlatformSharedStorageXFileCreationParams extends PlatformXFileCreationParams { - /// Constructs a [PlatformXFileCreationParams]. + /// Constructs a [PlatformSharedStorageXFileCreationParams]. const PlatformSharedStorageXFileCreationParams({required super.uri}); } /// Base mixin used to provide platform specific features for implementations of -/// [PlatformXFile]. +/// [PlatformSharedStorageXFile]. /// /// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformXFile.extension]. +/// this mixin and return an instance with [PlatformSharedStorageXFile.extension]. /// /// ```dart -/// base class AndroidPlatformXFile extends PlatformXFile with AndroidXFileExtension { +/// base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile with AndroidXFileExtension { /// // ... /// @override -/// PlatformXFileExtension? get extension => this; +/// PlatformSharedStorageXFileExtension? get extension => this; /// /// Future platformMethod() { /// // ... /// } /// } /// -/// mixin AndroidXFileExtension implements PlatformXFileExtension { +/// mixin AndroidXFileExtension implements PlatformSharedStorageXFileExtension { /// Future platformMethod(); /// } /// ``` -mixin SharedStoragePlatformXFileExtension implements PlatformXFileExtension {} +mixin PlatformSharedStorageXFileExtension implements PlatformXFileExtension {} -abstract base class PlatformSharedStorageXFile extends PlatformXFile { +/// Interface for a reference to a local data resource within a devices +/// shared storage. +abstract base class PlatformSharedStorageXFile + extends + PlatformXFile< + PlatformSharedStorageXFileCreationParams, + PlatformSharedStorageXFileExtension + > { /// Creates a new [PlatformSharedStorageXFile] factory PlatformSharedStorageXFile( PlatformSharedStorageXFileCreationParams params, @@ -74,30 +83,19 @@ abstract base class PlatformSharedStorageXFile extends PlatformXFile { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' - 'ensure that an implementation of `XFilePlatform` has been set to ' + 'ensure that an implementation of `CrossFilePlatform` has been set to ' '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); - final PlatformSharedStorageXFile file = CrossFilePlatform.instance! - .createPlatformSharedStorageXFile(params); - return file; + return CrossFilePlatform.instance!.createPlatformSharedStorageXFile(params); } - /// Used by the platform implementation to create a new [PlatformXFile]. + /// Used by the platform implementation to create a new + /// [PlatformSharedStorageXFile]. /// /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected PlatformSharedStorageXFile.implementation(super.params) : super.implementation(); - - /// The parameters used to initialize the [PlatformXFile]. - @override - PlatformSharedStorageXFileCreationParams get params => - super.params as PlatformSharedStorageXFileCreationParams; - - /// Extension for providing platform specific features. - @override - SharedStoragePlatformXFileExtension? get extension => - super.extension as SharedStoragePlatformXFileExtension?; } From cf2777da0763a4d53b8969d13e687bda841f2c16 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 13 Dec 2025 20:19:43 -0500 Subject: [PATCH 035/398] remove type annotations --- .../lib/src/cross_file_platform.dart | 13 +--- .../lib/src/platform_cross_directory.dart | 24 +++--- .../lib/src/platform_cross_file.dart | 14 ++-- .../lib/src/platform_cross_file_entity.dart | 9 +-- ...atform_shared_storage_cross_directory.dart | 16 ++-- .../platform_shared_storage_cross_file.dart | 17 ++--- .../cross_file_platform_interface_test.dart | 12 --- .../test/cross_file_platform_test.dart | 74 +++++++++++++++++++ 8 files changed, 114 insertions(+), 65 deletions(-) delete mode 100644 packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart create mode 100644 packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 367a17546a92..979c05e83e9c 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -18,18 +18,13 @@ abstract base class CrossFilePlatform { static CrossFilePlatform? instance; /// Creates a new [PlatformXFile]. - @optionalTypeArgs - PlatformXFile createPlatformXFile< - T extends PlatformXFileCreationParams, - S extends PlatformXFileExtension - >(PlatformXFileCreationParams params); + PlatformXFile createPlatformXFile(PlatformXFileCreationParams params); /// Creates a new [PlatformXDirectory]. @optionalTypeArgs - PlatformXDirectory createPlatformXDirectory< - T extends PlatformXDirectoryCreationParams, - S extends PlatformXDirectoryExtension - >(PlatformXDirectoryCreationParams params) { + PlatformXDirectory createPlatformXDirectory( + PlatformXDirectoryCreationParams params, + ) { throw UnimplementedError( 'createPlatformXDirectory is not implemented on the current platform.', ); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 7490687435f7..1762cb46fc7e 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -70,13 +70,9 @@ base class PlatformXDirectoryCreationParams mixin PlatformXDirectoryExtension implements PlatformXFileEntityExtension {} /// A reference to a directory (or folder) on the file system. -abstract base class PlatformXDirectory< - T extends PlatformXDirectoryCreationParams, - S extends PlatformXDirectoryExtension -> - extends PlatformXFileEntity { +abstract base class PlatformXDirectory extends PlatformXFileEntity { /// Creates a new [PlatformXDirectory]. - factory PlatformXDirectory(T params) { + factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' @@ -92,16 +88,16 @@ abstract base class PlatformXDirectory< /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformXDirectory.implementation(super.params); + PlatformXDirectory.implementation( + PlatformXDirectoryCreationParams super.params, + ); + + @override + PlatformXDirectoryCreationParams get params => + super.params as PlatformXDirectoryCreationParams; /// Lists the sub-directories and files of this Directory. - Stream< - PlatformXFileEntity< - PlatformXFileEntityCreationParams, - PlatformXFileEntityExtension - > - > - list(ListParams params); + Stream list(ListParams params); } /// Base class for parameters passed to [PlatformXDirectory.list]. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index e52081f83b28..41ca0176dcd3 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -70,13 +70,9 @@ base class PlatformXFileCreationParams mixin PlatformXFileExtension implements PlatformXFileEntityExtension {} /// Interface for a reference to a local data resource. -abstract base class PlatformXFile< - T extends PlatformXFileCreationParams, - S extends PlatformXFileExtension -> - extends PlatformXFileEntity { +abstract base class PlatformXFile extends PlatformXFileEntity { /// Creates a new [PlatformXFile]. - factory PlatformXFile(T params) { + factory PlatformXFile(PlatformXFileCreationParams params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' @@ -92,7 +88,11 @@ abstract base class PlatformXFile< /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformXFile.implementation(super.params); + PlatformXFile.implementation(PlatformXFileCreationParams super.params); + + @override + PlatformXFileCreationParams get params => + super.params as PlatformXFileCreationParams; /// Date and time when the resource was last modified, if the information is /// available. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart index 68f2407024e4..e908308dcc97 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart @@ -20,18 +20,15 @@ abstract base class PlatformXFileEntityCreationParams { mixin PlatformXFileEntityExtension {} /// The common superclass for [PlatformXFile] and [PlatformXDirectory]. -abstract base class PlatformXFileEntity< - T extends PlatformXFileEntityCreationParams, - S extends PlatformXFileEntityExtension -> { +abstract base class PlatformXFileEntity { /// Constructs a [PlatformCrossFileEntity]. PlatformXFileEntity(this.params); /// The parameters used to initialize the [PlatformXFileEntity]. - final T params; + final PlatformXFileEntityCreationParams params; /// Extension for providing platform specific features. - S? get extension => null; + PlatformXFileEntityExtension? get extension => null; /// Whether the resource represented by this reference exists. Future exists(); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart index 47b4bbc875b9..9d9713f7f62a 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart @@ -70,12 +70,7 @@ mixin SharedStoragePlatformXDirectoryExtension /// A reference to a directory (or folder) on the file system within a devices /// shared storage. -abstract base class PlatformSharedStorageXDirectory - extends - PlatformXDirectory< - PlatformSharedStorageXDirectoryCreationParams, - SharedStoragePlatformXDirectoryExtension - > { +abstract base class PlatformSharedStorageXDirectory extends PlatformXDirectory { /// Creates a new [PlatformSharedStorageXDirectory] factory PlatformSharedStorageXDirectory( PlatformSharedStorageXDirectoryCreationParams params, @@ -97,6 +92,11 @@ abstract base class PlatformSharedStorageXDirectory /// /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. - PlatformSharedStorageXDirectory.implementation(super.params) - : super.implementation(); + PlatformSharedStorageXDirectory.implementation( + PlatformSharedStorageXDirectoryCreationParams super.params, + ) : super.implementation(); + + @override + PlatformSharedStorageXDirectoryCreationParams get params => + super.params as PlatformSharedStorageXDirectoryCreationParams; } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart index cb1793c398c3..3840ab745448 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart @@ -7,7 +7,6 @@ import 'package:flutter/foundation.dart'; import '../cross_file_platform.dart'; import '../platform_cross_file.dart'; - /// Object specifying creation parameters for creating a [PlatformSharedStorageXFile]. /// /// Platform specific implementations can add additional fields by extending @@ -70,12 +69,7 @@ mixin PlatformSharedStorageXFileExtension implements PlatformXFileExtension {} /// Interface for a reference to a local data resource within a devices /// shared storage. -abstract base class PlatformSharedStorageXFile - extends - PlatformXFile< - PlatformSharedStorageXFileCreationParams, - PlatformSharedStorageXFileExtension - > { +abstract base class PlatformSharedStorageXFile extends PlatformXFile { /// Creates a new [PlatformSharedStorageXFile] factory PlatformSharedStorageXFile( PlatformSharedStorageXFileCreationParams params, @@ -96,6 +90,11 @@ abstract base class PlatformSharedStorageXFile /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformSharedStorageXFile.implementation(super.params) - : super.implementation(); + PlatformSharedStorageXFile.implementation( + PlatformSharedStorageXFileCreationParams super.params, + ) : super.implementation(); + + @override + PlatformSharedStorageXFileCreationParams get params => + super.params as PlatformSharedStorageXFileCreationParams; } diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart deleted file mode 100644 index f13a620eb830..000000000000 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_interface_test.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; - -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; - -void main() { - test('adds one to input values', () { - final calculator = Calculator(); - expect(calculator.addOne(2), 3); - expect(calculator.addOne(-7), -6); - expect(calculator.addOne(0), 1); - }); -} diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart new file mode 100644 index 000000000000..5319a9cf71fe --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -0,0 +1,74 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'dart:typed_data'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('CrossFilePlatform', () { + test( + 'Default implementation of createPlatformXDirectory should throw unimplemented error', + () { + final platform = TestCrossFilePlatform(); + + expect( + () => platform.createPlatformXDirectory( + const PlatformXDirectoryCreationParams(uri: 'test'), + ), + throwsUnimplementedError, + ); + }, + ); + }); +} + +final class TestCrossFilePlatform extends CrossFilePlatform { + @override + PlatformXFile createPlatformXFile(PlatformXFileCreationParams params) { + return TestXFile(params); + } +} + +final class TestXFile extends PlatformXFile { + TestXFile(super.params) : super.implementation(); + + @override + Future canRead() { + throw UnimplementedError(); + } + + @override + Future exists() { + throw UnimplementedError(); + } + + @override + Future lastModified() { + throw UnimplementedError(); + } + + @override + Future length() { + throw UnimplementedError(); + } + + @override + Stream> openRead([int? start, int? end]) { + throw UnimplementedError(); + } + + @override + Future readAsBytes() { + throw UnimplementedError(); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + throw UnimplementedError(); + } +} From 01997fbcafc895e137717e66db9543b01f05acda Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 13 Dec 2025 20:28:13 -0500 Subject: [PATCH 036/398] finish platform interface --- .../CHANGELOG.md | 2 +- .../cross_file_platform_interface/README.md | 46 ++++++------------- 2 files changed, 15 insertions(+), 33 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/CHANGELOG.md b/packages/cross_file/cross_file_platform_interface/CHANGELOG.md index 41cc7d8192ec..d0bd041d0ff6 100644 --- a/packages/cross_file/cross_file_platform_interface/CHANGELOG.md +++ b/packages/cross_file/cross_file_platform_interface/CHANGELOG.md @@ -1,3 +1,3 @@ ## 0.0.1 -* TODO: Describe initial release. +* Initial release. diff --git a/packages/cross_file/cross_file_platform_interface/README.md b/packages/cross_file/cross_file_platform_interface/README.md index 4a260d8d279a..bbe36d350d9e 100644 --- a/packages/cross_file/cross_file_platform_interface/README.md +++ b/packages/cross_file/cross_file_platform_interface/README.md @@ -1,39 +1,21 @@ - +This interface allows platform implementations of the `cross_file` plugin, as well as the plugin +itself, to ensure they are supporting the same interface. -TODO: Put a short description of the package here that helps potential users -know whether this package might be useful for them. +# Usage -## Features +To implement a new platform implementation of `cross_file`, extend +[`CrossFilePlatform`](lib/src/cross_file_platform.dart) with an implementation that performs the +platform-specific behavior, and when you register your plugin, set the default +`CrossFilePlatform` by calling `CrossFilePlatform.instance = CrossFileMyPlatform()`. -TODO: List what your package can do. Maybe include images, gifs, or videos. +# Note on breaking changes -## Getting started +Strongly prefer non-breaking changes (such as adding a method to the interface) +over breaking changes for this package. -TODO: List prerequisites and provide or point to information on how to -start using the package. - -## Usage - -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. - -```dart -const like = 'sample'; -``` - -## Additional information - -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +See https://flutter.dev/go/platform-interface-breaking-changes for a discussion on why a less-clean +interface is preferable to a breaking change. From 7e5a2da39e8d8f7fbfef4f41cbb14e8f666c1fb2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 13 Dec 2025 20:53:47 -0500 Subject: [PATCH 037/398] implemenation of cross file io --- .../cross_file/lib/src/cross_file.dart | 6 +-- .../lib/src/android_cross_file.dart | 4 ++ .../lib/src/cross_file_android.dart | 4 ++ packages/cross_file/cross_file_io/.gitignore | 31 ------------- packages/cross_file/cross_file_io/.metadata | 10 ----- packages/cross_file/cross_file_io/AUTHORS | 6 +++ .../cross_file/cross_file_io/CHANGELOG.md | 2 +- packages/cross_file/cross_file_io/LICENSE | 26 ++++++++++- .../cross_file_io/analysis_options.yaml | 4 -- .../cross_file_io/lib/cross_file_io.dart | 5 ++- .../cross_file_io/lib/src/cross_file_io.dart | 14 +++++- .../lib/src/io_cross_directory.dart | 44 +++++++++++++++++++ .../cross_file_io/lib/src/io_cross_file.dart | 15 +++++-- .../cross_file/cross_file_io/pubspec.yaml | 8 ++-- .../test/cross_file_io_test.dart | 2 + .../cross_file_platform_interface/AUTHORS | 6 +++ 16 files changed, 127 insertions(+), 60 deletions(-) delete mode 100644 packages/cross_file/cross_file_io/.gitignore delete mode 100644 packages/cross_file/cross_file_io/.metadata create mode 100644 packages/cross_file/cross_file_io/AUTHORS delete mode 100644 packages/cross_file/cross_file_io/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart create mode 100644 packages/cross_file/cross_file_platform_interface/AUTHORS diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index a27d2a78cd6e..2d16a758ee1b 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -8,8 +8,8 @@ import 'package:meta/meta.dart'; @immutable @optionalTypeArgs class XFile { - XFile(String path) - : this.fromPlatformCreationParams(PlatformXFileCreationParams(path: path)); + XFile(String uri) + : this.fromPlatformCreationParams(PlatformXFileCreationParams(uri: uri)); XFile.fromPlatformCreationParams(PlatformXFileCreationParams params) : this.fromPlatform(PlatformXFile(params)); @@ -18,7 +18,7 @@ class XFile { final PlatformXFile platform; - String get path => platform.params.path; + String get uri => platform.params.uri; /// Provides a nonnull platform class extension. /// diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index dae2f38ba31b..cd44127a080b 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:typed_data'; diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index ab54de262baf..0cb238245ce7 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + // Platform Implementation for Android import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; diff --git a/packages/cross_file/cross_file_io/.gitignore b/packages/cross_file/cross_file_io/.gitignore deleted file mode 100644 index dd5eb98951f2..000000000000 --- a/packages/cross_file/cross_file_io/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/cross_file/cross_file_io/.metadata b/packages/cross_file/cross_file_io/.metadata deleted file mode 100644 index c3035525beb4..000000000000 --- a/packages/cross_file/cross_file_io/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "241d31017403dd24234254fe39b5913714462ff5" - channel: "main" - -project_type: package diff --git a/packages/cross_file/cross_file_io/AUTHORS b/packages/cross_file/cross_file_io/AUTHORS new file mode 100644 index 000000000000..557dff97933b --- /dev/null +++ b/packages/cross_file/cross_file_io/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/packages/cross_file/cross_file_io/CHANGELOG.md b/packages/cross_file/cross_file_io/CHANGELOG.md index 41cc7d8192ec..d0bd041d0ff6 100644 --- a/packages/cross_file/cross_file_io/CHANGELOG.md +++ b/packages/cross_file/cross_file_io/CHANGELOG.md @@ -1,3 +1,3 @@ ## 0.0.1 -* TODO: Describe initial release. +* Initial release. diff --git a/packages/cross_file/cross_file_io/LICENSE b/packages/cross_file/cross_file_io/LICENSE index ba75c69f7f21..29b709dac6c7 100644 --- a/packages/cross_file/cross_file_io/LICENSE +++ b/packages/cross_file/cross_file_io/LICENSE @@ -1 +1,25 @@ -TODO: Add your license here. +Copyright 2013 The Flutter Authors + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/cross_file/cross_file_io/analysis_options.yaml b/packages/cross_file/cross_file_io/analysis_options.yaml deleted file mode 100644 index a5744c1cfbe7..000000000000 --- a/packages/cross_file/cross_file_io/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index a540f8df62de..b8fa2a34b670 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -1,2 +1,3 @@ - -c \ No newline at end of file +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index 2c3cc5834d92..1af3b979efc1 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -1,10 +1,15 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -// Platform Implementation for Android import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'io_cross_directory.dart'; import 'io_cross_file.dart'; +/// Implementation of [CrossFilePlatform] for dart:io. final class CrossFileIO extends CrossFilePlatform { + /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileIO(); } @@ -13,4 +18,11 @@ final class CrossFileIO extends CrossFilePlatform { IOXFile createPlatformXFile(PlatformXFileCreationParams params) { return IOXFile(params); } + + @override + IOXDirectory createPlatformXDirectory( + PlatformXDirectoryCreationParams params, + ) { + return IOXDirectory(params); + } } diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart new file mode 100644 index 000000000000..6ebaf574643f --- /dev/null +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -0,0 +1,44 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'io_cross_file.dart'; + +/// Implementation of [PlatformXDirectory] for dart:io. +base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { + /// Constructs an [IOXDirectory]. + IOXDirectory(super.params) : super.implementation(); + + @override + late final directory = Directory(params.uri); + + @override + IOXDirectoryExtension? get extension => this; + + @override + Future exists() async => directory.existsSync(); + + @override + Stream list(ListParams params) async* { + await for (final FileSystemEntity entity in directory.list()) { + switch (entity) { + case final Directory directory: + yield IOXDirectory( + PlatformXDirectoryCreationParams(uri: directory.path), + ); + case final File file: + yield IOXFile(PlatformXFileCreationParams(uri: file.path)); + } + } + } +} + +/// Provides platform specific features for [IOXDirectory]. +mixin IOXDirectoryExtension implements PlatformXDirectoryExtension { + /// The underlying directory. + Directory get directory; +} diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 61af921c9ed4..e15f3a4758ee 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -1,19 +1,26 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +/// Implementation of [PlatformXFile] for dart:io. base class IOXFile extends PlatformXFile with IOXFileExtension { + /// Constructs an [IOXFile]. IOXFile(super.params) : super.implementation(); - late final File file = File(params.path); + @override + late final file = File(params.uri); @override PlatformXFileExtension? get extension => this; @override - Future lastModified() => file.lastModified(); + Future lastModified() async => file.lastModifiedSync(); @override Future length() => file.length(); @@ -33,9 +40,11 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { Future canRead() => exists(); @override - Future exists() => file.exists(); + Future exists() async => file.existsSync(); } +/// Provides platform specific features for [IOXFile]. mixin IOXFileExtension implements PlatformXFileExtension { + /// The underlying file. File get file; } diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index b4bb35e1060f..166f194954be 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -1,9 +1,8 @@ name: cross_file_io description: Something something darkside -repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 +repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_io +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 -publish_to: none environment: sdk: ^3.9.0 @@ -19,4 +18,5 @@ dev_dependencies: flutter_test: sdk: flutter -flutter: +topics: + - files diff --git a/packages/cross_file/cross_file_io/test/cross_file_io_test.dart b/packages/cross_file/cross_file_io/test/cross_file_io_test.dart index 541dd06cae17..e64482fc1935 100644 --- a/packages/cross_file/cross_file_io/test/cross_file_io_test.dart +++ b/packages/cross_file/cross_file_io/test/cross_file_io_test.dart @@ -1,3 +1,5 @@ + + import 'package:flutter_test/flutter_test.dart'; import 'package:cross_file_io/cross_file_io.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/AUTHORS b/packages/cross_file/cross_file_platform_interface/AUTHORS new file mode 100644 index 000000000000..557dff97933b --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. From 934fe93068ae4cb0322294dac45e7a325d439baa Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 13 Dec 2025 22:30:19 -0500 Subject: [PATCH 038/398] io implementation --- .../cross_file_io/lib/cross_file_io.dart | 4 + .../lib/src/io_cross_directory.dart | 31 ++++++- .../cross_file_io/lib/src/io_cross_file.dart | 29 ++++++- .../cross_file/cross_file_io/pubspec.yaml | 1 + .../test/cross_file_io_test.dart | 14 ---- .../test/io_cross_directory_test.dart | 45 +++++++++++ .../test/io_cross_file_test.dart | 81 +++++++++++++++++++ .../cross_file_io/test/test_file.txt | 1 + 8 files changed, 190 insertions(+), 16 deletions(-) delete mode 100644 packages/cross_file/cross_file_io/test/cross_file_io_test.dart create mode 100644 packages/cross_file/cross_file_io/test/io_cross_directory_test.dart create mode 100644 packages/cross_file/cross_file_io/test/io_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_io/test/test_file.txt diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index b8fa2a34b670..53731439c334 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -1,3 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +export 'src/cross_file_io.dart'; +export 'src/io_cross_directory.dart' show IOXDirectoryExtension; +export 'src/io_cross_file.dart' show IOXFileCreationParams, IOXFileExtension; diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart index 6ebaf574643f..80eaac1e9b3b 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -5,16 +5,45 @@ import 'dart:io'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; import 'io_cross_file.dart'; +/// Implementation of [PlatformXDirectoryCreationParams] for dart:io. +@immutable +base class IOXDirectoryCreationParams extends PlatformXDirectoryCreationParams { + /// Constructs an [IOXDirectoryCreationParams]. + IOXDirectoryCreationParams({required String uri}) + : this.fromFile(Directory(uri)); + + /// Constructs an [IOXDirectoryCreationParams] from a [Directory]. + IOXDirectoryCreationParams.fromFile(this.directory) + : super(uri: directory.path); + + /// Constructs an [IOXDirectoryCreationParams] from a [PlatformXDirectoryCreationParams]. + factory IOXDirectoryCreationParams.fromCreationParams( + PlatformXDirectoryCreationParams params, + ) { + return IOXDirectoryCreationParams(uri: params.uri); + } + + /// The underlying [Directory] for [IOXDirectory]. + final Directory directory; +} + /// Implementation of [PlatformXDirectory] for dart:io. base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { /// Constructs an [IOXDirectory]. IOXDirectory(super.params) : super.implementation(); @override - late final directory = Directory(params.uri); + late final IOXDirectoryCreationParams params = + super.params is IOXDirectoryCreationParams + ? super.params as IOXDirectoryCreationParams + : IOXDirectoryCreationParams.fromCreationParams(super.params); + + @override + Directory get directory => params.directory; @override IOXDirectoryExtension? get extension => this; diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index e15f3a4758ee..95b0e9c6d9b4 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -7,6 +7,27 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; + +/// Implementation of [PlatformXFileCreationParams] for dart:io. +@immutable +base class IOXFileCreationParams extends PlatformXFileCreationParams { + /// Constructs an [IOXFileCreationParams]. + IOXFileCreationParams({required String uri}) : this.fromFile(File(uri)); + + /// Constructs an [IOXFileCreationParams] from a [File]. + IOXFileCreationParams.fromFile(this.file) : super(uri: file.path); + + /// Constructs an [IOXFileCreationParams] from a [PlatformXFileCreationParams]. + factory IOXFileCreationParams.fromCreationParams( + PlatformXFileCreationParams params, + ) { + return IOXFileCreationParams(uri: params.uri); + } + + /// The underlying [File] for [IOXFile]. + final File file; +} /// Implementation of [PlatformXFile] for dart:io. base class IOXFile extends PlatformXFile with IOXFileExtension { @@ -14,7 +35,13 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { IOXFile(super.params) : super.implementation(); @override - late final file = File(params.uri); + late final IOXFileCreationParams params = + super.params is IOXFileCreationParams + ? super.params as IOXFileCreationParams + : IOXFileCreationParams.fromCreationParams(super.params); + + @override + File get file => params.file; @override PlatformXFileExtension? get extension => this; diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index 166f194954be..922b0924095f 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -15,6 +15,7 @@ dependencies: path: ../cross_file_platform_interface dev_dependencies: + path: ^1.9.1 flutter_test: sdk: flutter diff --git a/packages/cross_file/cross_file_io/test/cross_file_io_test.dart b/packages/cross_file/cross_file_io/test/cross_file_io_test.dart deleted file mode 100644 index e64482fc1935..000000000000 --- a/packages/cross_file/cross_file_io/test/cross_file_io_test.dart +++ /dev/null @@ -1,14 +0,0 @@ - - -import 'package:flutter_test/flutter_test.dart'; - -import 'package:cross_file_io/cross_file_io.dart'; - -void main() { - test('adds one to input values', () { - final calculator = Calculator(); - expect(calculator.addOne(2), 3); - expect(calculator.addOne(-7), -6); - expect(calculator.addOne(0), 1); - }); -} diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart new file mode 100644 index 000000000000..5bfe565ff3d4 --- /dev/null +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -0,0 +1,45 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; + +final Directory testDirectory = Directory( + path.join(Directory.current.path, 'test'), +); + +void main() { + group('IOXFile', () { + setUp(() { + CrossFilePlatform.instance = CrossFileIO(); + }); + + test('exists', () async { + final directory = PlatformXDirectory( + PlatformXDirectoryCreationParams(uri: testDirectory.path), + ); + + expect(await directory.exists(), testDirectory.existsSync()); + }); + + test('list', () async { + final directory = PlatformXDirectory( + PlatformXDirectoryCreationParams(uri: testDirectory.path), + ); + + expect( + (await directory.list(ListParams()).toList()).map( + (PlatformXFileEntity entity) => entity.params.uri, + ), + (await testDirectory.list().toList()).map( + (FileSystemEntity entity) => entity.path, + ), + ); + }); + }); +} diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart new file mode 100644 index 000000000000..d30aaf92c0a4 --- /dev/null +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -0,0 +1,81 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; + +final File testFile = File( + path.join(Directory.current.path, 'test', 'test_file.txt'), +); + +void main() { + group('IOXFile', () { + setUp(() { + CrossFilePlatform.instance = CrossFileIO(); + }); + + test('lastModified', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.lastModified(), await testFile.lastModified()); + }); + + test('length', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.length(), await testFile.length()); + }); + + test('openRead', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect( + await file.openRead().toList(), + await testFile.openRead().toList(), + ); + }); + + test('readAsBytes', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.readAsBytes(), await testFile.readAsBytes()); + }); + + test('readAsString', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.readAsString(), await testFile.readAsString()); + }); + + test('canRead', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.canRead(), testFile.existsSync()); + }); + + test('exists', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.exists(), testFile.existsSync()); + }); + }); +} diff --git a/packages/cross_file/cross_file_io/test/test_file.txt b/packages/cross_file/cross_file_io/test/test_file.txt new file mode 100644 index 000000000000..b45ef6fec895 --- /dev/null +++ b/packages/cross_file/cross_file_io/test/test_file.txt @@ -0,0 +1 @@ +Hello, World! \ No newline at end of file From 8c3771d3a499525799c10e49309e13089d1e07b2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:31:09 -0500 Subject: [PATCH 039/398] android impl --- .../cross_file/cross_file_android/.gitignore | 33 - .../cross_file/cross_file_android/.metadata | 30 - .../cross_file_android/CHANGELOG.md | 2 +- .../cross_file/cross_file_android/LICENSE | 26 +- .../cross_file_android/analysis_options.yaml | 4 - .../CrossFileAndroidPlugin.kt | 4 + .../InputStreamReadBytesResponse.kt | 4 + .../cross_file_android/ProxyApiRegistrar.kt | 20 +- .../proxies/AndroidLibrary.g.kt | 969 ++++++++++++ .../proxies/DocumentFile.g.kt | 1348 ----------------- .../proxies/DocumentFileProxyApi.kt | 8 + .../proxies/InputStreamProxyApi.kt | 4 +- .../lib/cross_file_android.dart | 4 + .../lib/src/android_cross_file.dart | 52 +- ...ent_file.g.dart => android_library.g.dart} | 693 +++++---- .../lib/src/cross_file_android.dart | 17 +- .../pigeons/android_library.dart | 104 ++ .../pigeons/document_file.dart | 67 - .../cross_file_android/pubspec.yaml | 13 +- .../cross_file_io/lib/cross_file_io.dart | 4 +- .../cross_file_io/lib/src/cross_file_io.dart | 2 +- .../cross_file_io/lib/src/io_cross_file.dart | 1 - 22 files changed, 1514 insertions(+), 1895 deletions(-) delete mode 100644 packages/cross_file/cross_file_android/.gitignore delete mode 100644 packages/cross_file/cross_file_android/.metadata delete mode 100644 packages/cross_file/cross_file_android/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt delete mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt rename packages/cross_file/cross_file_android/lib/src/{document_file.g.dart => android_library.g.dart} (65%) create mode 100644 packages/cross_file/cross_file_android/pigeons/android_library.dart delete mode 100644 packages/cross_file/cross_file_android/pigeons/document_file.dart diff --git a/packages/cross_file/cross_file_android/.gitignore b/packages/cross_file/cross_file_android/.gitignore deleted file mode 100644 index b9d7f25b91b6..000000000000 --- a/packages/cross_file/cross_file_android/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/cross_file/cross_file_android/.metadata b/packages/cross_file/cross_file_android/.metadata deleted file mode 100644 index 4c1a47f79ebd..000000000000 --- a/packages/cross_file/cross_file_android/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "81928eeb91fcdb2bc7a2dc35622627b31581549f" - channel: "main" - -project_type: plugin - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - - platform: android - create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_android/CHANGELOG.md b/packages/cross_file/cross_file_android/CHANGELOG.md index 41cc7d8192ec..d0bd041d0ff6 100644 --- a/packages/cross_file/cross_file_android/CHANGELOG.md +++ b/packages/cross_file/cross_file_android/CHANGELOG.md @@ -1,3 +1,3 @@ ## 0.0.1 -* TODO: Describe initial release. +* Initial release. diff --git a/packages/cross_file/cross_file_android/LICENSE b/packages/cross_file/cross_file_android/LICENSE index ba75c69f7f21..29b709dac6c7 100644 --- a/packages/cross_file/cross_file_android/LICENSE +++ b/packages/cross_file/cross_file_android/LICENSE @@ -1 +1,25 @@ -TODO: Add your license here. +Copyright 2013 The Flutter Authors + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/cross_file/cross_file_android/analysis_options.yaml b/packages/cross_file/cross_file_android/analysis_options.yaml deleted file mode 100644 index a5744c1cfbe7..000000000000 --- a/packages/cross_file/cross_file_android/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt index 841e192fe62c..277bd0b5e9c5 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + package dev.flutter.packages.cross_file_android import io.flutter.embedding.engine.plugins.FlutterPlugin diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt index f88d96e03cf0..2a2d9b75058d 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + package dev.flutter.packages.cross_file_android data class InputStreamReadBytesResponse(val returnValue: Int, val bytes: ByteArray) { diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt index 37679e97cfb2..d5475fca2596 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + package dev.flutter.packages.cross_file_android import android.content.Context @@ -5,8 +9,8 @@ import android.os.Build import android.os.Handler import android.os.Looper import androidx.annotation.ChecksSdkIntAtLeast +import dev.flutter.packages.cross_file_android.proxies.AndroidLibraryPigeonProxyApiRegistrar import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi -import dev.flutter.packages.cross_file_android.proxies.DocumentFilePigeonProxyApiRegistrar import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi import dev.flutter.packages.cross_file_android.proxies.InputStreamProxyApi import dev.flutter.packages.cross_file_android.proxies.InputStreamReadBytesResponseProxyApi @@ -21,19 +25,7 @@ import io.flutter.plugin.common.BinaryMessenger * implementation and any additional resources needed by an implementation. */ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Context) : - DocumentFilePigeonProxyApiRegistrar(binaryMessenger) { - - // Added to be overriden for tests. The test implementation calls `callback` immediately, instead - // of waiting for the main thread to run it. - internal open fun runOnMainThread(callback: Runnable) { - Handler(Looper.getMainLooper()).post { callback.run() } - } - - // Interface for an injectable SDK version checker. - @ChecksSdkIntAtLeast(parameter = 0) - open fun sdkIsAtLeast(version: Int): Boolean { - return Build.VERSION.SDK_INT >= version - } + AndroidLibraryPigeonProxyApiRegistrar(binaryMessenger) { override fun getPigeonApiDocumentFile(): PigeonApiDocumentFile { return DocumentFileProxyApi(this) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt new file mode 100644 index 000000000000..a5f0b65af700 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -0,0 +1,969 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// See also: https://pub.dev/packages/pigeon +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +package dev.flutter.packages.cross_file_android.proxies + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer +private object AndroidLibraryPigeonUtils { + + fun createConnectionError(channelName: String): FlutterError { + return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + + fun wrapResult(result: Any?): List { + return listOf(result) + } + + fun wrapError(exception: Throwable): List { + return if (exception is FlutterError) { + listOf( + exception.code, + exception.message, + exception.details + ) + } else { + listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) + } + } +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +/** + * Maintains instances used to communicate with the corresponding objects in Dart. + * + * Objects stored in this container are represented by an object in Dart that is also stored in + * an InstanceManager with the same identifier. + * + * When an instance is added with an identifier, either can be used to retrieve the other. + * + * Added instances are added as a weak reference and a strong reference. When the strong + * reference is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong + * reference is removed and then the identifier is retrieved with the intention to pass the identifier + * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance + * is recreated. The strong reference will then need to be removed manually again. + */ +@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") +class AndroidLibraryPigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ + interface PigeonFinalizationListener { + fun onFinalize(identifier: Long) + } + + // Extends WeakReference and overrides the `equals` and `hashCode` methods using identity rather + // than equality. + // + // Two `IdentityWeakReference`s are equal if either + // 1: `get()` returns the identical nonnull value for both references. + // 2: `get()` returns null for both references and the references are identical. + class IdentityWeakReference : java.lang.ref.WeakReference { + private val savedHashCode: Int + + constructor(instance: T) : this(instance, null) + + constructor(instance: T, queue: java.lang.ref.ReferenceQueue?) : super(instance, queue) { + savedHashCode = System.identityHashCode(instance) + } + + override fun equals(other: Any?): Boolean { + val instance = get() + if (instance != null) { + return other is IdentityWeakReference<*> && other.get() === instance + } + return other === this + } + + override fun hashCode(): Int { + return savedHashCode + } + } + + private val identifiers = java.util.WeakHashMap, Long>() + private val weakInstances = HashMap>() + private val strongInstances = HashMap() + private val referenceQueue = java.lang.ref.ReferenceQueue() + private val weakReferencesToIdentifiers = HashMap, Long>() + private val handler = android.os.Handler(android.os.Looper.getMainLooper()) + private val releaseAllFinalizedInstancesRunnable = Runnable { + this.releaseAllFinalizedInstances() + } + private var nextIdentifier: Long = minHostCreatedIdentifier + private var hasFinalizationListenerStopped = false + + /** + * Modifies the time interval used to define how often this instance removes garbage collected + * weak references to native Android objects that this instance was managing. + */ + var clearFinalizedWeakReferencesInterval: Long = 3000 + set(value) { + handler.removeCallbacks(releaseAllFinalizedInstancesRunnable) + field = value + releaseAllFinalizedInstances() + } + + init { + handler.postDelayed(releaseAllFinalizedInstancesRunnable, clearFinalizedWeakReferencesInterval) + } + + companion object { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private const val minHostCreatedIdentifier: Long = 65536 + private const val tag = "PigeonInstanceManager" + + /** + * Instantiate a new manager with a listener for garbage collected weak + * references. + * + * When the manager is no longer needed, [stopFinalizationListener] must be called. + */ + fun create(finalizationListener: PigeonFinalizationListener): AndroidLibraryPigeonInstanceManager { + return AndroidLibraryPigeonInstanceManager(finalizationListener) + } + } + + /** + * Removes `identifier` and return its associated strongly referenced instance, if present, + * from the manager. + */ + fun remove(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + return strongInstances.remove(identifier) as T? + } + + /** + * Retrieves the identifier paired with an instance, if present, otherwise `null`. + * + * + * If the manager contains a strong reference to `instance`, it will return the identifier + * associated with `instance`. If the manager contains only a weak reference to `instance`, a new + * strong reference to `instance` will be added and will need to be removed again with [remove]. + * + * + * If this method returns a nonnull identifier, this method also expects the Dart + * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. + */ + fun getIdentifierForStrongReference(instance: Any?): Long? { + logWarningIfFinalizationListenerHasStopped() + if (instance == null) { + return null + } + val identifier = identifiers[IdentityWeakReference(instance)] + if (identifier != null) { + strongInstances[identifier] = instance + } + return identifier + } + + /** + * Adds a new instance that was instantiated from Dart. + * + * The same instance can be added multiple times, but each identifier must be unique. This + * allows two objects that are equivalent (e.g. the `equals` method returns true and their + * hashcodes are equal) to both be added. + * + * [identifier] must be >= 0 and unique. + */ + fun addDartCreatedInstance(instance: Any, identifier: Long) { + logWarningIfFinalizationListenerHasStopped() + addInstance(instance, identifier) + } + + /** + * Adds a new unique instance that was instantiated from the host platform. + * + * If the manager contains [instance], this returns the corresponding identifier. If the + * manager does not contain [instance], this adds the instance and returns a unique + * identifier for that [instance]. + */ + fun addHostCreatedInstance(instance: Any): Long { + logWarningIfFinalizationListenerHasStopped() + require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } + val identifier = nextIdentifier++ + addInstance(instance, identifier) + return identifier + } + + /** Retrieves the instance associated with identifier, if present, otherwise `null`. */ + fun getInstance(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + val instance = weakInstances[identifier] as IdentityWeakReference? + return instance?.get() + } + + /** Returns whether this manager contains the given `instance`. */ + fun containsInstance(instance: Any?): Boolean { + logWarningIfFinalizationListenerHasStopped() + return instance != null && identifiers.containsKey(IdentityWeakReference(instance)) + } + + /** + * Stops the periodic run of the [PigeonFinalizationListener] for instances that have been garbage + * collected. + * + * The InstanceManager can continue to be used, but the [PigeonFinalizationListener] will no + * longer be called and methods will log a warning. + */ + fun stopFinalizationListener() { + handler.removeCallbacks(releaseAllFinalizedInstancesRunnable) + hasFinalizationListenerStopped = true + } + + /** + * Removes all of the instances from this manager. + * + * The manager will be empty after this call returns. + */ + fun clear() { + identifiers.clear() + weakInstances.clear() + strongInstances.clear() + weakReferencesToIdentifiers.clear() + } + + /** + * Whether the [PigeonFinalizationListener] is still being called for instances that are garbage + * collected. + * + * See [stopFinalizationListener]. + */ + fun hasFinalizationListenerStopped(): Boolean { + return hasFinalizationListenerStopped + } + + private fun releaseAllFinalizedInstances() { + if (hasFinalizationListenerStopped()) { + return + } + var reference: IdentityWeakReference? + while ((referenceQueue.poll() as IdentityWeakReference?).also { reference = it } != null) { + val identifier = weakReferencesToIdentifiers.remove(reference) + if (identifier != null) { + weakInstances.remove(identifier) + strongInstances.remove(identifier) + finalizationListener.onFinalize(identifier) + } + } + handler.postDelayed(releaseAllFinalizedInstancesRunnable, clearFinalizedWeakReferencesInterval) + } + + private fun addInstance(instance: Any, identifier: Long) { + require(identifier >= 0) { "Identifier must be >= 0: $identifier" } + require(!weakInstances.containsKey(identifier)) { + "Identifier has already been added: $identifier" + } + val weakReference = IdentityWeakReference(instance, referenceQueue) + identifiers[weakReference] = identifier + weakInstances[identifier] = weakReference + weakReferencesToIdentifiers[weakReference] = identifier + strongInstances[identifier] = instance + } + + private fun logWarningIfFinalizationListenerHasStopped() { + if (hasFinalizationListenerStopped()) { + Log.w( + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped." + ) + } + } +} + + +/** Generated API for managing the Dart and native `InstanceManager`s. */ +private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { + companion object { + /** The codec used by AndroidLibraryPigeonInstanceManagerApi. */ + val codec: MessageCodec by lazy { + AndroidLibraryPigeonCodec() + } + + /** + * Sets up an instance of `AndroidLibraryPigeonInstanceManagerApi` to handle messages from the + * `binaryMessenger`. + */ + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: AndroidLibraryPigeonInstanceManager?) { + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) + if (instanceManager != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val identifierArg = args[0] as Long + val wrapped: List = try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) + if (instanceManager != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) +{ + val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) + } + } + } +} +/** + * Provides implementations for each ProxyApi implementation and provides access to resources + * needed by any implementation. + */ +abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { + /** Whether APIs should ignore calling to Dart. */ + public var ignoreCallsToDart = false + val instanceManager: AndroidLibraryPigeonInstanceManager + private var _codec: MessageCodec? = null + val codec: MessageCodec + get() { + if (_codec == null) { + _codec = AndroidLibraryPigeonProxyApiBaseCodec(this) + } + return _codec!! + } + + init { + val api = AndroidLibraryPigeonInstanceManagerApi(binaryMessenger) + instanceManager = AndroidLibraryPigeonInstanceManager.create( + object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier" + ) + } + } + } + } + ) + } + /** + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of + * `DocumentFile` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile + + /** + * An implementation of [PigeonApiContentResolver] used to add a new Dart instance of + * `ContentResolver` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiContentResolver(): PigeonApiContentResolver + + /** + * An implementation of [PigeonApiInputStreamReadBytesResponse] used to add a new Dart instance of + * `InputStreamReadBytesResponse` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse + + /** + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of + * `InputStream` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiInputStream(): PigeonApiInputStream + + fun setUp() { + AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, instanceManager) + PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, getPigeonApiDocumentFile()) + PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) + PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) + } + fun tearDown() { + AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) + PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) + PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, null) + PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) + } +} +private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibraryPigeonProxyApiRegistrar) : AndroidLibraryPigeonCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + val identifier: Long = readValue(buffer) as Long + val instance: Any? = registrar.instanceManager.getInstance(identifier) + if (instance == null) { + Log.e( + "PigeonProxyApiBaseCodec", + "Failed to find instance with identifier: $identifier" + ) + } + return instance + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { + super.writeValue(stream, value) + return + } + + fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { + Log.w( + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception" + ) + } + + if (value is androidx.documentfile.provider.DocumentFile) { + registrar.getPigeonApiDocumentFile().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) + } + } + } + else if (value is android.content.ContentResolver) { + registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) + } + } + } + else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) + } + } + } + else if (value is java.io.InputStream) { + registrar.getPigeonApiInputStream().pigeon_newInstance(value) { + if (it.isFailure) { + logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) + } + } + } + + when { + registrar.instanceManager.containsInstance(value) -> { + stream.write(128) + writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) + } + else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") + } + } +} +private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return super.readValueOfType(type, buffer) + } + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + super.writeValue(stream, value) + } +} + +/** + * Representation of a document backed by either a + * android.provider.DocumentsProvider or a raw file on disk. + * + * See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. + */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** Create a DocumentFile representing the single document at the given Uri. */ + abstract fun fromSingleUri(path: String): androidx.documentfile.provider.DocumentFile + + /** Indicates whether the current context is allowed to read from this file. */ + abstract fun canRead(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + /** Deletes this file. */ + abstract fun delete(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + /** Returns a boolean indicating whether this file can be found. */ + abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + /** + * Returns the time when this file was last modified, measured in + * milliseconds since January 1st, 1970, midnight. + */ + abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long + + /** Returns the length of this file in bytes. */ + abstract fun length(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long + + /** Indicates if this file represents a *file*. */ + abstract fun isFile(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + /** Indicates if this file represents a *directory*. */ + abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { + val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0] as Long + val pathArg = args[1] as String + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(pathArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.isFile(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.isDirectory(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} +/** + * This class provides applications access to the content model. + * + * See https://developer.android.com/reference/kotlin/android/content/ContentResolver + */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * Helper field for accessing the `ContentResolver` from the current Android + * `Context`. + */ + abstract fun instance(): android.content.ContentResolver + + /** Open a stream on to the content associated with a content URI. */ + abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { + val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0] as Long + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as android.content.ContentResolver + val uriArg = args[1] as String + val wrapped: List = try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} +/** Return type for [InputStream.readBytes] that handles returning two values. */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long + + abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val returnValueArg = returnValue(pigeon_instanceArg) + val bytesArg = bytes(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} +/** + * This abstract class is the superclass of all classes representing an input + * stream of bytes. + * + * See https://developer.android.com/reference/java/io/InputStream. + */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * Reads some number of bytes from the input stream and stores them into the + * returns them. + */ + abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long, off: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + + /** Reads all remaining bytes from the input stream. */ + abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray + + /** Skips over and discards n bytes of data from this input stream. */ + abstract fun skip(pigeon_instance: java.io.InputStream, n: Long): Long + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { + val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as java.io.InputStream + val lenArg = args[1] as Long + val offArg = args[2] as Long + val wrapped: List = try { + listOf(api.readBytes(pigeon_instanceArg, lenArg, offArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as java.io.InputStream + val wrapped: List = try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as java.io.InputStream + val nArg = args[1] as Long + val wrapped: List = try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) +{ + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + callback(Result.success(Unit)) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) + } + } + } + } + +} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt deleted file mode 100644 index bfd84e00cf38..000000000000 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt +++ /dev/null @@ -1,1348 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon -@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") - -package dev.flutter.packages.cross_file_android.proxies - -import android.util.Log -import io.flutter.plugin.common.BasicMessageChannel -import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMessageCodec -import java.io.ByteArrayOutputStream -import java.nio.ByteBuffer - -private object DocumentFilePigeonUtils { - - fun createConnectionError(channelName: String): FlutterError { - return FlutterError( - "channel-error", "Unable to establish connection on channel: '$channelName'.", "") - } - - fun wrapResult(result: Any?): List { - return listOf(result) - } - - fun wrapError(exception: Throwable): List { - return if (exception is FlutterError) { - listOf(exception.code, exception.message, exception.details) - } else { - listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) - } - } -} - -/** - * Error class for passing custom error details to Flutter via a thrown PlatformException. - * - * @property code The error code. - * @property message The error message. - * @property details The error details. Must be a datatype supported by the api codec. - */ -class FlutterError( - val code: String, - override val message: String? = null, - val details: Any? = null -) : Throwable() -/** - * Maintains instances used to communicate with the corresponding objects in Dart. - * - * Objects stored in this container are represented by an object in Dart that is also stored in an - * InstanceManager with the same identifier. - * - * When an instance is added with an identifier, either can be used to retrieve the other. - * - * Added instances are added as a weak reference and a strong reference. When the strong reference - * is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the - * strong reference is removed and then the identifier is retrieved with the intention to pass the - * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the - * instance is recreated. The strong reference will then need to be removed manually again. - */ -@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class DocumentFilePigeonInstanceManager( - private val finalizationListener: PigeonFinalizationListener -) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ - interface PigeonFinalizationListener { - fun onFinalize(identifier: Long) - } - - // Extends WeakReference and overrides the `equals` and `hashCode` methods using identity rather - // than equality. - // - // Two `IdentityWeakReference`s are equal if either - // 1: `get()` returns the identical nonnull value for both references. - // 2: `get()` returns null for both references and the references are identical. - class IdentityWeakReference : java.lang.ref.WeakReference { - private val savedHashCode: Int - - constructor(instance: T) : this(instance, null) - - constructor(instance: T, queue: java.lang.ref.ReferenceQueue?) : super(instance, queue) { - savedHashCode = System.identityHashCode(instance) - } - - override fun equals(other: Any?): Boolean { - val instance = get() - if (instance != null) { - return other is IdentityWeakReference<*> && other.get() === instance - } - return other === this - } - - override fun hashCode(): Int { - return savedHashCode - } - } - - private val identifiers = java.util.WeakHashMap, Long>() - private val weakInstances = HashMap>() - private val strongInstances = HashMap() - private val referenceQueue = java.lang.ref.ReferenceQueue() - private val weakReferencesToIdentifiers = HashMap, Long>() - private val handler = android.os.Handler(android.os.Looper.getMainLooper()) - private val releaseAllFinalizedInstancesRunnable = Runnable { - this.releaseAllFinalizedInstances() - } - private var nextIdentifier: Long = minHostCreatedIdentifier - private var hasFinalizationListenerStopped = false - - /** - * Modifies the time interval used to define how often this instance removes garbage collected - * weak references to native Android objects that this instance was managing. - */ - var clearFinalizedWeakReferencesInterval: Long = 3000 - set(value) { - handler.removeCallbacks(releaseAllFinalizedInstancesRunnable) - field = value - releaseAllFinalizedInstances() - } - - init { - handler.postDelayed(releaseAllFinalizedInstancesRunnable, clearFinalizedWeakReferencesInterval) - } - - companion object { - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously from Dart. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - private const val minHostCreatedIdentifier: Long = 65536 - private const val tag = "PigeonInstanceManager" - - /** - * Instantiate a new manager with a listener for garbage collected weak references. - * - * When the manager is no longer needed, [stopFinalizationListener] must be called. - */ - fun create( - finalizationListener: PigeonFinalizationListener - ): DocumentFilePigeonInstanceManager { - return DocumentFilePigeonInstanceManager(finalizationListener) - } - } - - /** - * Removes `identifier` and return its associated strongly referenced instance, if present, from - * the manager. - */ - fun remove(identifier: Long): T? { - logWarningIfFinalizationListenerHasStopped() - return strongInstances.remove(identifier) as T? - } - - /** - * Retrieves the identifier paired with an instance, if present, otherwise `null`. - * - * If the manager contains a strong reference to `instance`, it will return the identifier - * associated with `instance`. If the manager contains only a weak reference to `instance`, a new - * strong reference to `instance` will be added and will need to be removed again with [remove]. - * - * If this method returns a nonnull identifier, this method also expects the Dart - * `DocumentFilePigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance - * the identifier is associated with. - */ - fun getIdentifierForStrongReference(instance: Any?): Long? { - logWarningIfFinalizationListenerHasStopped() - if (instance == null) { - return null - } - val identifier = identifiers[IdentityWeakReference(instance)] - if (identifier != null) { - strongInstances[identifier] = instance - } - return identifier - } - - /** - * Adds a new instance that was instantiated from Dart. - * - * The same instance can be added multiple times, but each identifier must be unique. This allows - * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are - * equal) to both be added. - * - * [identifier] must be >= 0 and unique. - */ - fun addDartCreatedInstance(instance: Any, identifier: Long) { - logWarningIfFinalizationListenerHasStopped() - addInstance(instance, identifier) - } - - /** - * Adds a new unique instance that was instantiated from the host platform. - * - * If the manager contains [instance], this returns the corresponding identifier. If the manager - * does not contain [instance], this adds the instance and returns a unique identifier for that - * [instance]. - */ - fun addHostCreatedInstance(instance: Any): Long { - logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { - "Instance of ${instance.javaClass} has already been added." - } - val identifier = nextIdentifier++ - addInstance(instance, identifier) - return identifier - } - - /** Retrieves the instance associated with identifier, if present, otherwise `null`. */ - fun getInstance(identifier: Long): T? { - logWarningIfFinalizationListenerHasStopped() - val instance = weakInstances[identifier] as IdentityWeakReference? - return instance?.get() - } - - /** Returns whether this manager contains the given `instance`. */ - fun containsInstance(instance: Any?): Boolean { - logWarningIfFinalizationListenerHasStopped() - return instance != null && identifiers.containsKey(IdentityWeakReference(instance)) - } - - /** - * Stops the periodic run of the [PigeonFinalizationListener] for instances that have been garbage - * collected. - * - * The InstanceManager can continue to be used, but the [PigeonFinalizationListener] will no - * longer be called and methods will log a warning. - */ - fun stopFinalizationListener() { - handler.removeCallbacks(releaseAllFinalizedInstancesRunnable) - hasFinalizationListenerStopped = true - } - - /** - * Removes all of the instances from this manager. - * - * The manager will be empty after this call returns. - */ - fun clear() { - identifiers.clear() - weakInstances.clear() - strongInstances.clear() - weakReferencesToIdentifiers.clear() - } - - /** - * Whether the [PigeonFinalizationListener] is still being called for instances that are garbage - * collected. - * - * See [stopFinalizationListener]. - */ - fun hasFinalizationListenerStopped(): Boolean { - return hasFinalizationListenerStopped - } - - private fun releaseAllFinalizedInstances() { - if (hasFinalizationListenerStopped()) { - return - } - var reference: IdentityWeakReference? - while ((referenceQueue.poll() as IdentityWeakReference?).also { reference = it } != null) { - val identifier = weakReferencesToIdentifiers.remove(reference) - if (identifier != null) { - weakInstances.remove(identifier) - strongInstances.remove(identifier) - finalizationListener.onFinalize(identifier) - } - } - handler.postDelayed(releaseAllFinalizedInstancesRunnable, clearFinalizedWeakReferencesInterval) - } - - private fun addInstance(instance: Any, identifier: Long) { - require(identifier >= 0) { "Identifier must be >= 0: $identifier" } - require(!weakInstances.containsKey(identifier)) { - "Identifier has already been added: $identifier" - } - val weakReference = IdentityWeakReference(instance, referenceQueue) - identifiers[weakReference] = identifier - weakInstances[identifier] = weakReference - weakReferencesToIdentifiers[weakReference] = identifier - strongInstances[identifier] = instance - } - - private fun logWarningIfFinalizationListenerHasStopped() { - if (hasFinalizationListenerStopped()) { - Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped.") - } - } -} - -/** Generated API for managing the Dart and native `InstanceManager`s. */ -private class DocumentFilePigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { - companion object { - /** The codec used by DocumentFilePigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { DocumentFilePigeonCodec() } - - /** - * Sets up an instance of `DocumentFilePigeonInstanceManagerApi` to handle messages from the - * `binaryMessenger`. - */ - fun setUpMessageHandlers( - binaryMessenger: BinaryMessenger, - instanceManager: DocumentFilePigeonInstanceManager? - ) { - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", - codec) - if (instanceManager != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val identifierArg = args[0] as Long - val wrapped: List = - try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", - codec) - if (instanceManager != null) { - channel.setMessageHandler { _, reply -> - val wrapped: List = - try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } - - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { - val channelName = - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(identifierArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } - } - } -} -/** - * Provides implementations for each ProxyApi implementation and provides access to resources needed - * by any implementation. - */ -abstract class DocumentFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { - /** Whether APIs should ignore calling to Dart. */ - public var ignoreCallsToDart = false - val instanceManager: DocumentFilePigeonInstanceManager - private var _codec: MessageCodec? = null - val codec: MessageCodec - get() { - if (_codec == null) { - _codec = DocumentFilePigeonProxyApiBaseCodec(this) - } - return _codec!! - } - - init { - val api = DocumentFilePigeonInstanceManagerApi(binaryMessenger) - instanceManager = - DocumentFilePigeonInstanceManager.create( - object : DocumentFilePigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier") - } - } - } - }) - } - /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` - * to the Dart `InstanceManager`. - */ - abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile - - /** - * An implementation of [PigeonApiContentResolver] used to add a new Dart instance of - * `ContentResolver` to the Dart `InstanceManager`. - */ - abstract fun getPigeonApiContentResolver(): PigeonApiContentResolver - - /** - * An implementation of [PigeonApiInputStreamReadBytesResponse] used to add a new Dart instance of - * `InputStreamReadBytesResponse` to the Dart `InstanceManager`. - */ - abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse - - /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to - * the Dart `InstanceManager`. - */ - abstract fun getPigeonApiInputStream(): PigeonApiInputStream - - fun setUp() { - DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, instanceManager) - PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, getPigeonApiDocumentFile()) - PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) - PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) - } - - fun tearDown() { - DocumentFilePigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) - PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) - PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, null) - PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) - } -} - -private class DocumentFilePigeonProxyApiBaseCodec( - val registrar: DocumentFilePigeonProxyApiRegistrar -) : DocumentFilePigeonCodec() { - override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return when (type) { - 128.toByte() -> { - val identifier: Long = readValue(buffer) as Long - val instance: Any? = registrar.instanceManager.getInstance(identifier) - if (instance == null) { - Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") - } - return instance - } - else -> super.readValueOfType(type, buffer) - } - } - - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || - value is ByteArray || - value is Double || - value is DoubleArray || - value is FloatArray || - value is Int || - value is IntArray || - value is List<*> || - value is Long || - value is LongArray || - value is Map<*, *> || - value is String || - value == null) { - super.writeValue(stream, value) - return - } - - fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { - Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception") - } - - if (value is androidx.documentfile.provider.DocumentFile) { - registrar.getPigeonApiDocumentFile().pigeon_newInstance(value) { - if (it.isFailure) { - logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) - } - } - } else if (value is android.content.ContentResolver) { - registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { - if (it.isFailure) { - logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) - } - } - } else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { - registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { - if (it.isFailure) { - logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) - } - } - } else if (value is java.io.InputStream) { - registrar.getPigeonApiInputStream().pigeon_newInstance(value) { - if (it.isFailure) { - logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) - } - } - } - - when { - registrar.instanceManager.containsInstance(value) -> { - stream.write(128) - writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) - } - else -> - throw IllegalArgumentException( - "Unsupported value: '$value' of type '${value.javaClass.name}'") - } - } -} - -private open class DocumentFilePigeonCodec : StandardMessageCodec() { - override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) - } - - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - super.writeValue(stream, value) - } -} - -@Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile( - open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar -) { - abstract fun fromSingleUri(path: String): androidx.documentfile.provider.DocumentFile - - abstract fun canRead(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - - abstract fun delete(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - - abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - - abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long - - abstract fun length(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long - - companion object { - @Suppress("LocalVariableName") - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { - val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_identifierArg = args[0] as Long - val pathArg = args[1] as String - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.fromSingleUri(pathArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } - - @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, - callback: (Result) -> Unit - ) { - if (pigeonRegistrar.ignoreCallsToDart) { - callback( - Result.failure( - FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { - callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) - val binaryMessenger = pigeonRegistrar.binaryMessenger - val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(pigeon_identifierArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import androidx.documentfile.provider.DocumentFile - -/** - * ProxyApi implementation for [DocumentFile]. - * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. - */ -class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiDocumentFile(pigeonRegistrar) { - - override fun fromSingleUri(path: String): DocumentFile { - return DocumentFile(path) - } - - override fun canRead(pigeon_instance: DocumentFile): Boolean { - return pigeon_instance.canRead() - } - - override fun delete(pigeon_instance: DocumentFile): Boolean { - return pigeon_instance.delete() - } - - override fun exists(pigeon_instance: DocumentFile): Boolean { - return pigeon_instance.exists() - } - - override fun lastModified(pigeon_instance: DocumentFile): Long { - return pigeon_instance.lastModified() - } - - override fun length(pigeon_instance: DocumentFile): Long { - return pigeon_instance.length() - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import androidx.documentfile.provider.DocumentFile -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever - -class DocumentFileTest { - @Test - fun fromSingleUri() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - assertTrue(api.fromSingleUri("myString") is DocumentFileProxyApi.DocumentFile) - } - - @Test - fun canRead() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = true - whenever(instance.canRead()).thenReturn(value) - - assertEquals(value, api.canRead(instance )) - } - - @Test - fun delete() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = true - whenever(instance.delete()).thenReturn(value) - - assertEquals(value, api.delete(instance )) - } - - @Test - fun exists() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = true - whenever(instance.exists()).thenReturn(value) - - assertEquals(value, api.exists(instance )) - } - - @Test - fun lastModified() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = 0 - whenever(instance.lastModified()).thenReturn(value) - - assertEquals(value, api.lastModified(instance )) - } - - @Test - fun length() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = 0 - whenever(instance.length()).thenReturn(value) - - assertEquals(value, api.length(instance )) - } - -} -*/ -/** https://developer.android.com/reference/kotlin/android/content/ContentResolver */ -@Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver( - open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar -) { - abstract fun instance(): android.content.ContentResolver - - abstract fun openInputStream( - pigeon_instance: android.content.ContentResolver, - uri: String - ): java.io.InputStream? - - companion object { - @Suppress("LocalVariableName") - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { - val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_identifierArg = args[0] as Long - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as android.content.ContentResolver - val uriArg = args[1] as String - val wrapped: List = - try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } - - @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: android.content.ContentResolver, - callback: (Result) -> Unit - ) { - if (pigeonRegistrar.ignoreCallsToDart) { - callback( - Result.failure( - FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { - callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) - val binaryMessenger = pigeonRegistrar.binaryMessenger - val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(pigeon_identifierArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import android.content.ContentResolver -import java.io.InputStream - -/** - * ProxyApi implementation for [ContentResolver]. - * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. - */ -class ContentResolverProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiContentResolver(pigeonRegistrar) { - - override fun instance(): android.content.ContentResolver { - return ContentResolver.instance - } - - override fun openInputStream(pigeon_instance: ContentResolver,uri: String): java.io.InputStream? { - return pigeon_instance.openInputStream(uri) - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import android.content.ContentResolver -import java.io.InputStream -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever - -class ContentResolverTest { - @Test - fun openInputStream() { - val api = TestProxyApiRegistrar().getPigeonApiContentResolver() - - val instance = mock() - val uri = "myString" - val value = mock() - whenever(instance.openInputStream(uri)).thenReturn(value) - - assertEquals(value, api.openInputStream(instance, uri)) - } - -} -*/ -@Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse( - open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar -) { - abstract fun returnValue( - pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - ): Long - - abstract fun bytes( - pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - ): ByteArray - - @Suppress("LocalVariableName", "FunctionName") - /** - * Creates a Dart instance of InputStreamReadBytesResponse and attaches it to - * [pigeon_instanceArg]. - */ - fun pigeon_newInstance( - pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, - callback: (Result) -> Unit - ) { - if (pigeonRegistrar.ignoreCallsToDart) { - callback( - Result.failure( - FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { - callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) - val returnValueArg = returnValue(pigeon_instanceArg) - val bytesArg = bytes(pigeon_instanceArg) - val binaryMessenger = pigeonRegistrar.binaryMessenger - val codec = pigeonRegistrar.codec - val channelName = - "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - -/** - * ProxyApi implementation for [InputStreamReadBytesResponse]. - * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. - */ -class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStreamReadBytesResponse(pigeonRegistrar) { - - override fun returnValue(pigeon_instance: InputStreamReadBytesResponse): Long { - return pigeon_instance.returnValue - } - - override fun bytes(pigeon_instance: InputStreamReadBytesResponse): ByteArray { - return pigeon_instance.bytes - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever - -class InputStreamReadBytesResponseTest { - @Test - fun returnValue() { - val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() - - val instance = mock() - val value = 0 - whenever(instance.returnValue).thenReturn(value) - - assertEquals(value, api.returnValue(instance)) - } - - @Test - fun bytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() - - val instance = mock() - val value = byteArrayOf(0xA1.toByte()) - whenever(instance.bytes).thenReturn(value) - - assertEquals(value, api.bytes(instance)) - } - -} -*/ -@Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStream(open val pigeonRegistrar: DocumentFilePigeonProxyApiRegistrar) { - abstract fun readBytes( - pigeon_instance: java.io.InputStream, - len: Long - ): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - - abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray - - abstract fun skip(pigeon_instance: java.io.InputStream, n: Long): Long - - companion object { - @Suppress("LocalVariableName") - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { - val codec = api?.pigeonRegistrar?.codec ?: DocumentFilePigeonCodec() - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as java.io.InputStream - val lenArg = args[1] as Long - val wrapped: List = - try { - listOf(api.readBytes(pigeon_instanceArg, lenArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", - codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = - try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) - if (api != null) { - channel.setMessageHandler { message, reply -> - val args = message as List - val pigeon_instanceArg = args[0] as java.io.InputStream - val nArg = args[1] as Long - val wrapped: List = - try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - DocumentFilePigeonUtils.wrapError(exception) - } - reply.reply(wrapped) - } - } else { - channel.setMessageHandler(null) - } - } - } - } - - @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: java.io.InputStream, - callback: (Result) -> Unit - ) { - if (pigeonRegistrar.ignoreCallsToDart) { - callback( - Result.failure( - FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { - callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) - val binaryMessenger = pigeonRegistrar.binaryMessenger - val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(pigeon_identifierArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(DocumentFilePigeonUtils.createConnectionError(channelName))) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import java.io.InputStream -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - -/** - * ProxyApi implementation for [InputStream]. - * - * This class may handle instantiating native object instances that are attached to a Dart - * instance or handle method calls on the associated native class or an instance of that class. - */ -class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStream(pigeonRegistrar) { - - override fun readBytes(pigeon_instance: InputStream,len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse { - return pigeon_instance.readBytes(len) - } - - override fun readAllBytes(pigeon_instance: InputStream): ByteArray { - return pigeon_instance.readAllBytes() - } - - override fun skip(pigeon_instance: InputStream,n: Long): Long { - return pigeon_instance.skip(n) - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import java.io.InputStream -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.Mockito -import org.mockito.kotlin.any -import org.mockito.kotlin.eq -import org.mockito.kotlin.mock -import org.mockito.kotlin.verify -import org.mockito.kotlin.whenever - -class InputStreamTest { - @Test - fun readBytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStream() - - val instance = mock() - val len = 0 - val value = mock() - whenever(instance.readBytes(len)).thenReturn(value) - - assertEquals(value, api.readBytes(instance, len)) - } - - @Test - fun readAllBytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStream() - - val instance = mock() - val value = byteArrayOf(0xA1.toByte()) - whenever(instance.readAllBytes()).thenReturn(value) - - assertEquals(value, api.readAllBytes(instance )) - } - - @Test - fun skip() { - val api = TestProxyApiRegistrar().getPigeonApiInputStream() - - val instance = mock() - val n = 0 - val value = 0 - whenever(instance.skip(n)).thenReturn(value) - - assertEquals(value, api.skip(instance, n)) - } - -} -*/ diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt index cdba1030b671..421d6f44c045 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt @@ -40,4 +40,12 @@ class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : override fun length(pigeon_instance: DocumentFile): Long { return pigeon_instance.length() } + + override fun isFile(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.isFile + } + + override fun isDirectory(pigeon_instance: DocumentFile): Boolean { + return pigeon_instance.isDirectory + } } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt index eda56173a221..fb4407e18e8e 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -16,9 +16,9 @@ import java.io.InputStream */ class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStream(pigeonRegistrar) { - override fun readBytes(pigeon_instance: InputStream, len: Long): InputStreamReadBytesResponse { + override fun readBytes(pigeon_instance: InputStream, len: Long, off: Long): InputStreamReadBytesResponse { val bytes = ByteArray(len.toInt()) - return InputStreamReadBytesResponse(pigeon_instance.read(bytes), bytes) + return InputStreamReadBytesResponse(pigeon_instance.read(bytes, off.toInt(), bytes.size), bytes) } override fun readAllBytes(pigeon_instance: InputStream): ByteArray { diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 6d9b4deabbbb..2ef13e71c7fc 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'src/android_cross_file.dart'; export 'src/cross_file_android.dart'; export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart index cd44127a080b..77d0350dfd94 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart @@ -3,16 +3,20 @@ // found in the LICENSE file. import 'dart:convert'; +import 'dart:math'; import 'dart:typed_data'; -import 'package:cross_file_android/src/document_file.g.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -base class AndroidXFile extends PlatformSharedStorageXFile { - AndroidXFile(super.params) : super.implementation(); +import 'android_library.g.dart'; + +/// Implementation of [PlatformSharedStorageXFile] for Android. +base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { + /// Constructs an [AndroidSharedStorageXFile]. + AndroidSharedStorageXFile(super.params) : super.implementation(); late final DocumentFile _documentFile = DocumentFile.fromSingleUri( - path: params.path, + path: params.uri, ); late final ContentResolver _contentResolver = ContentResolver.instance; @@ -29,17 +33,28 @@ base class AndroidXFile extends PlatformSharedStorageXFile { @override Stream openRead([int? start, int? end]) async* { + int bytesToRead = (end ?? await length()) - (start ?? 0); + assert(bytesToRead >= 0); + final InputStream? inputStream = await _contentResolver.openInputStream( - params.path, + params.uri, ); - // TODO: add support for start and end. - if (inputStream case InputStream inputStream) { + + const int maxByteArrayLen = 4 * 1024; + + if (inputStream case final InputStream inputStream) { InputStreamReadBytesResponse response = await inputStream.readBytes( - 4 * 1024, + min(bytesToRead, maxByteArrayLen), + start ?? 0, ); - while (response.returnValue != -1) { + bytesToRead -= response.returnValue; + while (response.returnValue != -1 && bytesToRead > 0) { yield response.bytes; - response = await inputStream.readBytes(4 * 1024); + response = await inputStream.readBytes( + min(bytesToRead, maxByteArrayLen), + 0, + ); + bytesToRead -= response.returnValue; } } else { throw _createNullInputStreamError(); @@ -49,9 +64,9 @@ base class AndroidXFile extends PlatformSharedStorageXFile { @override Future readAsBytes() async { final InputStream? inputStream = await _contentResolver.openInputStream( - params.path, + params.uri, ); - if (inputStream case InputStream inputStream) { + if (inputStream case final InputStream inputStream) { return inputStream.readAllBytes(); } @@ -67,21 +82,14 @@ base class AndroidXFile extends PlatformSharedStorageXFile { Future canRead() => _documentFile.canRead(); @override - Future exists() { - // TODO: shoulc also call _documentFile.isFile - return _documentFile.exists(); + Future exists() async { + return await _documentFile.exists() && await _documentFile.isFile(); } UnsupportedError _createNullInputStreamError() { return UnsupportedError( - 'Failed to get native InputStream from file with path: ${params.path}. ' + 'Failed to get native InputStream from file with path: ${params.uri}. ' 'App may not have permissions to access file.', ); } - - @override - Future delete() { - // TODO: implement delete - throw UnimplementedError(); - } } diff --git a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart similarity index 65% rename from packages/cross_file/cross_file_android/lib/src/document_file.g.dart rename to packages/cross_file/cross_file_android/lib/src/android_library.g.dart index cb367ce53273..7f61a3fab108 100644 --- a/packages/cross_file/cross_file_android/lib/src/document_file.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -1,16 +1,15 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.0), do not edit directly. +// Autogenerated from Pigeon (v26.1.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' - show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -21,11 +20,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -34,7 +29,6 @@ List wrapResponse({ } return [error.code, error.message, error.details]; } - /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -46,7 +40,7 @@ List wrapResponse({ class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String path})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -70,7 +64,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -140,10 +134,9 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> - _weakInstances = >{}; - final Map _strongInstances = - {}; + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -156,8 +149,7 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = - _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -165,21 +157,11 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers( - instanceManager: instanceManager, - ); - DocumentFile.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - ContentResolver.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStream.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -196,9 +178,8 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference( - instance, - ); + _weakInstances[identifier] = + WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -259,21 +240,15 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference( - int identifier, - ) { - final PigeonInternalProxyApiBaseClass? weakInstance = - _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = - _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance - .pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = - WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -295,10 +270,7 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance( - PigeonInternalProxyApiBaseClass instance, - int identifier, - ) { + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -327,7 +299,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -339,37 +311,29 @@ class _PigeonInternalInstanceManagerApi { PigeonInstanceManager? instanceManager, }) { { - final BasicMessageChannel - pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert( - arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', - ); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); try { - (instanceManager ?? PigeonInstanceManager.instance).remove( - arg_identifier!, - ); + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -377,19 +341,16 @@ class _PigeonInternalInstanceManagerApi { } Future removeStrongReference(int identifier) async { - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -407,17 +368,15 @@ class _PigeonInternalInstanceManagerApi { /// /// This is typically called after a hot restart. Future clear() async { - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -433,31 +392,31 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference( - readValue(buffer)! as int, - ); - default: - return super.readValueOfType(type, buffer); - } - } + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } } + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -478,8 +437,12 @@ class _PigeonCodec extends StandardMessageCodec { } } } - +/// Representation of a document backed by either a +/// android.provider.DocumentsProvider or a raw file on disk. +/// +/// See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. class DocumentFile extends PigeonInternalProxyApiBaseClass { + /// Create a DocumentFile representing the single document at the given Uri. factory DocumentFile.fromSingleUri({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, @@ -495,31 +458,29 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { ); } + /// Create a DocumentFile representing the single document at the given Uri. @protected DocumentFile.pigeon_fromSingleUri({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, required String path, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, path], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier, path]); () async { - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -555,70 +516,60 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel - pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } } } + /// Indicates whether the current context is allowed to read from this file. Future canRead() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.canRead'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -637,23 +588,21 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Deletes this file. Future delete() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.delete'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -672,23 +621,21 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Returns a boolean indicating whether this file can be found. Future exists() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.exists'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -707,23 +654,22 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Returns the time when this file was last modified, measured in + /// milliseconds since January 1st, 1970, midnight. Future lastModified() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -742,23 +688,21 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Returns the length of this file in bytes. Future length() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.length'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -777,6 +721,72 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Indicates if this file represents a *file*. + Future isFile() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.isFile'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + /// Indicates if this file represents a *directory*. + Future isDirectory() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + @override DocumentFile pigeon_copy() { return DocumentFile.pigeon_detached( @@ -786,7 +796,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } -/// https://developer.android.com/reference/kotlin/android/content/ContentResolver +/// This class provides applications access to the content model. +/// +/// See https://developer.android.com/reference/kotlin/android/content/ContentResolver class ContentResolver extends PigeonInternalProxyApiBaseClass { /// Constructs [ContentResolver] without creating the associated native object. /// @@ -801,8 +813,12 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecContentResolver = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + /// Helper field for accessing the `ContentResolver` from the current Android + /// `Context`. static final ContentResolver _instance = pigeonVar_instance(); + /// Helper field for accessing the `ContentResolver` from the current Android + /// `Context`. static ContentResolver get instance => PigeonOverrides.contentResolver_instance ?? _instance; @@ -814,47 +830,39 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel - pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -871,19 +879,16 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance .addDartCreatedInstance(pigeonVar_instance); () async { - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.ContentResolver.instance'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -899,23 +904,21 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { return pigeonVar_instance; } + /// Open a stream on to the content associated with a content URI. Future openInputStream(String uri) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecContentResolver; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, uri], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, uri]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -938,6 +941,7 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { } } +/// Return type for [InputStream.readBytes] that handles returning two values. class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { /// Constructs [InputStreamReadBytesResponse] without creating the associated native object. /// @@ -959,64 +963,54 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function(int returnValue, Uint8List bytes)? - pigeon_newInstance, + InputStreamReadBytesResponse Function( + int returnValue, + Uint8List bytes, + )? pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel - pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); final int? arg_returnValue = (args[1] as int?); - assert( - arg_returnValue != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_returnValue != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert( - arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.', - ); + assert(arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - returnValue: arg_returnValue!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: arg_returnValue!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1034,6 +1028,10 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { } } +/// This abstract class is the superclass of all classes representing an input +/// stream of bytes. +/// +/// See https://developer.android.com/reference/java/io/InputStream. class InputStream extends PigeonInternalProxyApiBaseClass { /// Constructs [InputStream] without creating the associated native object. /// @@ -1056,70 +1054,64 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { - final BasicMessageChannel - pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } } } - Future readBytes(int len) async { + /// Reads some number of bytes from the input stream and stores them into the + /// returns them. + Future readBytes( + int len, + int off, + ) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.InputStream.readBytes'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, len], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, len, off]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -1138,23 +1130,21 @@ class InputStream extends PigeonInternalProxyApiBaseClass { } } + /// Reads all remaining bytes from the input stream. Future readAllBytes() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -1173,23 +1163,21 @@ class InputStream extends PigeonInternalProxyApiBaseClass { } } + /// Skips over and discards n bytes of data from this input stream. Future skip(int n) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.InputStream.skip'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, n], + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, ); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, n]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); } else if (pigeonVar_replyList.length > 1) { @@ -1216,3 +1204,4 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } + diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index 0cb238245ce7..50d85153e4c4 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -2,27 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Platform Implementation for Android +import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'android_cross_file.dart'; -final class CrossFileAndroid extends CrossFilePlatform { +/// Implementation of [CrossFilePlatform] for Android. +base class CrossFileAndroid extends CrossFileIO { + /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileAndroid(); } @override - AndroidXFile createPlatformXFile(PlatformXFileCreationParams params) { - return createPlatformSharedStorageXFile( - PlatformSharedStorageXFileCreationParams(path: params.path), - ); - } - - @override - AndroidXFile createPlatformSharedStorageXFile( + AndroidSharedStorageXFile createPlatformSharedStorageXFile( PlatformSharedStorageXFileCreationParams params, ) { - return AndroidXFile(params); + return AndroidSharedStorageXFile(params); } } diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart new file mode 100644 index 000000000000..60632868d9d4 --- /dev/null +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -0,0 +1,104 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_unused_constructor_parameters + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/android_library.g.dart', + kotlinOut: + 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt', + kotlinOptions: KotlinOptions( + package: 'dev.flutter.packages.cross_file_android.proxies', + ), + copyrightHeader: 'pigeons/copyright.txt', + ), +) +/// Representation of a document backed by either a +/// android.provider.DocumentsProvider or a raw file on disk. +/// +/// See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: 'androidx.documentfile.provider.DocumentFile', + ), +) +abstract class DocumentFile { + /// Create a DocumentFile representing the single document at the given Uri. + DocumentFile.fromSingleUri(String path); + + /// Indicates whether the current context is allowed to read from this file. + bool canRead(); + + /// Deletes this file. + bool delete(); + + /// Returns a boolean indicating whether this file can be found. + bool exists(); + + /// Returns the time when this file was last modified, measured in + /// milliseconds since January 1st, 1970, midnight. + int lastModified(); + + /// Returns the length of this file in bytes. + int length(); + + /// Indicates if this file represents a *file*. + bool isFile(); + + /// Indicates if this file represents a *directory*. + bool isDirectory(); +} + +/// This class provides applications access to the content model. +/// +/// See https://developer.android.com/reference/kotlin/android/content/ContentResolver +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: 'android.content.ContentResolver', + ), +) +abstract class ContentResolver { + /// Helper field for accessing the `ContentResolver` from the current Android + /// `Context`. + @static + late final ContentResolver instance; + + /// Open a stream on to the content associated with a content URI. + InputStream? openInputStream(String uri); +} + +/// Return type for [InputStream.readBytes] that handles returning two values. +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: + 'dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse', + ), +) +abstract class InputStreamReadBytesResponse { + late final int returnValue; + + late final Uint8List bytes; +} + +/// This abstract class is the superclass of all classes representing an input +/// stream of bytes. +/// +/// See https://developer.android.com/reference/java/io/InputStream. +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), +) +abstract class InputStream { + /// Reads some number of bytes from the input stream and stores them into the + /// returns them. + InputStreamReadBytesResponse readBytes(int len, int off); + + /// Reads all remaining bytes from the input stream. + Uint8List readAllBytes(); + + /// Skips over and discards n bytes of data from this input stream. + int skip(int n); +} diff --git a/packages/cross_file/cross_file_android/pigeons/document_file.dart b/packages/cross_file/cross_file_android/pigeons/document_file.dart deleted file mode 100644 index b24db90ad70f..000000000000 --- a/packages/cross_file/cross_file_android/pigeons/document_file.dart +++ /dev/null @@ -1,67 +0,0 @@ -import 'package:pigeon/pigeon.dart'; - -@ConfigurePigeon( - PigeonOptions( - dartOut: 'lib/src/document_file.g.dart', - kotlinOut: - 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFile.g.kt', - kotlinOptions: KotlinOptions( - package: 'dev.flutter.packages.cross_file_android.proxies', - ), - copyrightHeader: 'pigeons/copyright.txt', - ), -) -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions( - fullClassName: 'androidx.documentfile.provider.DocumentFile', - ), -) -abstract class DocumentFile { - DocumentFile.fromSingleUri(String path); - - bool canRead(); - - bool delete(); - - bool exists(); - - int lastModified(); - - int length(); -} - -/// https://developer.android.com/reference/kotlin/android/content/ContentResolver -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions( - fullClassName: 'android.content.ContentResolver', - ), -) -abstract class ContentResolver { - @static - late final ContentResolver instance; - - InputStream? openInputStream(String uri); -} - -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions( - fullClassName: - 'dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse', - ), -) -abstract class InputStreamReadBytesResponse { - late final int returnValue; - - late final Uint8List bytes; -} - -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), -) -abstract class InputStream { - InputStreamReadBytesResponse readBytes(int len); - - Uint8List readAllBytes(); - - int skip(int n); -} diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index a93133ada491..749db2b72f6a 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -1,9 +1,8 @@ name: cross_file_android description: Some something darkside -repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 +repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_android +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 -publish_to: none environment: sdk: ^3.9.0 @@ -19,15 +18,17 @@ flutter: dartPluginClass: CrossFileAndroid dependencies: - flutter: - sdk: flutter + cross_file_io: + path: ../cross_file_io cross_file_platform_interface: path: ../cross_file_platform_interface + flutter: + sdk: flutter dev_dependencies: flutter_test: sdk: flutter - pigeon: ^26.1.0 + pigeon: ^26.1.4 topics: - file diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 53731439c334..4656879fad22 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -3,5 +3,5 @@ // found in the LICENSE file. export 'src/cross_file_io.dart'; -export 'src/io_cross_directory.dart' show IOXDirectoryExtension; -export 'src/io_cross_file.dart' show IOXFileCreationParams, IOXFileExtension; +export 'src/io_cross_directory.dart'; +export 'src/io_cross_file.dart'; diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index 1af3b979efc1..4382dbce0a9e 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -8,7 +8,7 @@ import 'io_cross_directory.dart'; import 'io_cross_file.dart'; /// Implementation of [CrossFilePlatform] for dart:io. -final class CrossFileIO extends CrossFilePlatform { +base class CrossFileIO extends CrossFilePlatform { /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileIO(); diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 95b0e9c6d9b4..c8cf3a90edb9 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -4,7 +4,6 @@ import 'dart:convert'; import 'dart:io'; -import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; From f30ffbcfe8412b0345d1aef57cf59498cf976a0f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:59:25 -0500 Subject: [PATCH 040/398] finish android impl --- .../InputStreamReadBytesResponse.kt | 1 + .../cross_file_android/ProxyApiRegistrar.kt | 2 +- .../proxies/AndroidLibrary.g.kt | 70 ++++++++- .../proxies/DocumentFileProxyApi.kt | 16 +- .../lib/cross_file_android.dart | 3 - ...ndroid_cross_shared_storage_directory.dart | 40 +++++ ...=> android_cross_shared_storage_file.dart} | 2 +- .../lib/src/android_library.g.dart | 137 +++++++++++++++++- .../lib/src/cross_file_android.dart | 10 +- .../pigeons/android_library.dart | 11 +- .../cross_file_io/lib/cross_file_io.dart | 4 +- 11 files changed, 275 insertions(+), 21 deletions(-) create mode 100644 packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_directory.dart rename packages/cross_file/cross_file_android/lib/src/{android_cross_file.dart => android_cross_shared_storage_file.dart} (99%) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt index 2a2d9b75058d..d77fd0471131 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt @@ -4,6 +4,7 @@ package dev.flutter.packages.cross_file_android +/** Represents the result of reading bytes from an [java.io.InputStream]. */ data class InputStreamReadBytesResponse(val returnValue: Int, val bytes: ByteArray) { override fun equals(other: Any?): Boolean { if (this === other) return true diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt index d5475fca2596..b6be27260d37 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -21,7 +21,7 @@ import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStreamReadB import io.flutter.plugin.common.BinaryMessenger /** - * Implementation of [InteractiveMediaAdsLibraryPigeonProxyApiRegistrar] that provides each ProxyApi + * Implementation of [AndroidLibraryPigeonProxyApiRegistrar] that provides each ProxyApi * implementation and any additional resources needed by an implementation. */ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Context) : diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index a5f0b65af700..267c71410226 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -523,7 +523,9 @@ private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { @Suppress("UNCHECKED_CAST") abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { /** Create a DocumentFile representing the single document at the given Uri. */ - abstract fun fromSingleUri(path: String): androidx.documentfile.provider.DocumentFile + abstract fun fromSingleUri(singleUri: String): androidx.documentfile.provider.DocumentFile + + abstract fun fromTreeUri(treeUri: String): androidx.documentfile.provider.DocumentFile /** Indicates whether the current context is allowed to read from this file. */ abstract fun canRead(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean @@ -549,6 +551,15 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig /** Indicates if this file represents a *directory*. */ abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean + /** + * Returns an list of files contained in the directory represented by this + * file. + */ + abstract fun listFiles(pigeon_instance: androidx.documentfile.provider.DocumentFile): List + + /** A Uri for the underlying document represented by this file. */ + abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String + companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { @@ -559,9 +570,28 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val pathArg = args[1] as String + val singleUriArg = args[1] as String + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(singleUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0] as Long + val treeUriArg = args[1] as String val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(pathArg), pigeon_identifierArg) + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromTreeUri(treeUriArg), pigeon_identifierArg) listOf(null) } catch (exception: Throwable) { AndroidLibraryPigeonUtils.wrapError(exception) @@ -691,6 +721,40 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig channel.setMessageHandler(null) } } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.listFiles(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = try { + listOf(api.getUri(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt index 421d6f44c045..2c7d8117d692 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt @@ -16,9 +16,13 @@ import dev.flutter.packages.cross_file_android.ProxyApiRegistrar */ class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiDocumentFile(pigeonRegistrar) { - override fun fromSingleUri(path: String): DocumentFile { + override fun fromSingleUri(singleUri: String): DocumentFile { // Only returns null on platforms below Android 19. - return DocumentFile.fromSingleUri(pigeonRegistrar.context, path.toUri())!! + return DocumentFile.fromSingleUri(pigeonRegistrar.context, singleUri.toUri())!! + } + + override fun fromTreeUri(treeUri: String): DocumentFile { + return DocumentFile.fromTreeUri(pigeonRegistrar.context, treeUri.toUri())!! } override fun canRead(pigeon_instance: DocumentFile): Boolean { @@ -48,4 +52,12 @@ class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : override fun isDirectory(pigeon_instance: DocumentFile): Boolean { return pigeon_instance.isDirectory } + + override fun listFiles(pigeon_instance: DocumentFile): List { + return pigeon_instance.listFiles().toList() + } + + override fun getUri(pigeon_instance: DocumentFile): String { + return pigeon_instance.uri.toString() + } } diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 2ef13e71c7fc..2e1a0ac21dc9 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -2,7 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -export 'src/android_cross_file.dart'; export 'src/cross_file_android.dart'; -export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show PlatformXFileCreationParams; diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_directory.dart new file mode 100644 index 000000000000..d74f3d895413 --- /dev/null +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_directory.dart @@ -0,0 +1,40 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'android_cross_shared_storage_file.dart'; +import 'android_library.g.dart'; + +/// Implementation of [PlatformSharedStorageXDirectory] for Android. +base class AndroidSharedStorageXDirectory + extends PlatformSharedStorageXDirectory { + /// Constructs an [AndroidSharedStorageXDirectory]. + AndroidSharedStorageXDirectory(super.params) : super.implementation(); + + late final DocumentFile _documentFile = DocumentFile.fromTreeUri( + treeUri: params.uri, + ); + + @override + Future exists() async { + return await _documentFile.exists() && await _documentFile.isDirectory(); + } + + @override + Stream list(ListParams params) async* { + for (final DocumentFile documentFile in await _documentFile.listFiles()) { + final String uri = await documentFile.getUri(); + if (await documentFile.isFile()) { + yield AndroidSharedStorageXFile( + PlatformSharedStorageXFileCreationParams(uri: uri), + ); + } else if (await documentFile.isDirectory()) { + yield AndroidSharedStorageXDirectory( + PlatformSharedStorageXDirectoryCreationParams(uri: uri), + ); + } + } + } +} diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart similarity index 99% rename from packages/cross_file/cross_file_android/lib/src/android_cross_file.dart rename to packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart index 77d0350dfd94..715516f9eb98 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart @@ -16,7 +16,7 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { AndroidSharedStorageXFile(super.params) : super.implementation(); late final DocumentFile _documentFile = DocumentFile.fromSingleUri( - path: params.uri, + singleUri: params.uri, ); late final ContentResolver _contentResolver = ContentResolver.instance; diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index 7f61a3fab108..2cdee6ecc48e 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -39,15 +39,20 @@ List wrapResponse({Object? result, PlatformException? error, bool empty @visibleForTesting class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. - static DocumentFile Function({required String path})? + static DocumentFile Function({required String singleUri})? documentFile_fromSingleUri; + /// Overrides [DocumentFile.fromTreeUri]. + static DocumentFile Function({required String treeUri})? + documentFile_fromTreeUri; + /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { documentFile_fromSingleUri = null; + documentFile_fromTreeUri = null; contentResolver_instance = null; } } @@ -446,15 +451,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { factory DocumentFile.fromSingleUri({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - required String path, + required String singleUri, }) { if (PigeonOverrides.documentFile_fromSingleUri != null) { - return PigeonOverrides.documentFile_fromSingleUri!(path: path); + return PigeonOverrides.documentFile_fromSingleUri!(singleUri: singleUri); } return DocumentFile.pigeon_fromSingleUri( pigeon_binaryMessenger: pigeon_binaryMessenger, pigeon_instanceManager: pigeon_instanceManager, - path: path, + singleUri: singleUri, ); } @@ -463,7 +468,7 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { DocumentFile.pigeon_fromSingleUri({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, - required String path, + required String singleUri, }) { final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); @@ -477,8 +482,59 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier, path]); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([pigeonVar_instanceIdentifier, singleUri]); + () async { + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + } + + factory DocumentFile.fromTreeUri({ + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + required String treeUri, + }) { + if (PigeonOverrides.documentFile_fromTreeUri != null) { + return PigeonOverrides.documentFile_fromTreeUri!(treeUri: treeUri); + } + return DocumentFile.pigeon_fromTreeUri( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + treeUri: treeUri, + ); + } + + @protected + DocumentFile.pigeon_fromTreeUri({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required String treeUri, + }) { + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([pigeonVar_instanceIdentifier, treeUri]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -787,6 +843,73 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Returns an list of files contained in the directory represented by this + /// file. + Future> listFiles() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } + + /// A Uri for the underlying document represented by this file. + Future getUri() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.getUri'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as String?)!; + } + } + @override DocumentFile pigeon_copy() { return DocumentFile.pigeon_detached( diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index 50d85153e4c4..b8e45bcaf2dd 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -5,7 +5,8 @@ import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'android_cross_file.dart'; +import 'android_cross_shared_storage_directory.dart'; +import 'android_cross_shared_storage_file.dart'; /// Implementation of [CrossFilePlatform] for Android. base class CrossFileAndroid extends CrossFileIO { @@ -20,4 +21,11 @@ base class CrossFileAndroid extends CrossFileIO { ) { return AndroidSharedStorageXFile(params); } + + @override + PlatformSharedStorageXDirectory createPlatformSharedStorageXDirectory( + PlatformSharedStorageXDirectoryCreationParams params, + ) { + return AndroidSharedStorageXDirectory(params); + } } diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index 60632868d9d4..77ff97184812 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -28,7 +28,9 @@ import 'package:pigeon/pigeon.dart'; ) abstract class DocumentFile { /// Create a DocumentFile representing the single document at the given Uri. - DocumentFile.fromSingleUri(String path); + DocumentFile.fromSingleUri(String singleUri); + + DocumentFile.fromTreeUri(String treeUri); /// Indicates whether the current context is allowed to read from this file. bool canRead(); @@ -51,6 +53,13 @@ abstract class DocumentFile { /// Indicates if this file represents a *directory*. bool isDirectory(); + + /// Returns an list of files contained in the directory represented by this + /// file. + List listFiles(); + + /// A Uri for the underlying document represented by this file. + String getUri(); } /// This class provides applications access to the content model. diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 4656879fad22..12b82d6e8335 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -3,5 +3,5 @@ // found in the LICENSE file. export 'src/cross_file_io.dart'; -export 'src/io_cross_directory.dart'; -export 'src/io_cross_file.dart'; +export 'src/io_cross_directory.dart' show IOXDirectoryCreationParams, IOXDirectoryExtension; +export 'src/io_cross_file.dart' show IOXFileCreationParams, IOXFileExtension; From 1c4c018d3138a3510e8866626237866371964c94 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 18 Dec 2025 17:16:14 -0500 Subject: [PATCH 041/398] web implementation --- packages/cross_file/cross_file_web/.gitignore | 33 ---------- packages/cross_file/cross_file_web/.metadata | 30 --------- .../cross_file_web/analysis_options.yaml | 4 -- .../cross_file_web/lib/cross_file_web.dart | 11 +++- .../lib/src/cross_file_web.dart | 6 ++ .../lib/src/web_cross_file.dart | 66 +++++++++++++++---- .../cross_file_web/lib/src/web_helpers.dart | 25 ++----- .../cross_file/cross_file_web/pubspec.yaml | 5 +- 8 files changed, 76 insertions(+), 104 deletions(-) delete mode 100644 packages/cross_file/cross_file_web/.gitignore delete mode 100644 packages/cross_file/cross_file_web/.metadata delete mode 100644 packages/cross_file/cross_file_web/analysis_options.yaml diff --git a/packages/cross_file/cross_file_web/.gitignore b/packages/cross_file/cross_file_web/.gitignore deleted file mode 100644 index b9d7f25b91b6..000000000000 --- a/packages/cross_file/cross_file_web/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/cross_file/cross_file_web/.metadata b/packages/cross_file/cross_file_web/.metadata deleted file mode 100644 index edd69034d058..000000000000 --- a/packages/cross_file/cross_file_web/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "7b98d50631e52399041060ae2ae19163cd5cba87" - channel: "main" - -project_type: plugin - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 - base_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 - - platform: web - create_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 - base_revision: 7b98d50631e52399041060ae2ae19163cd5cba87 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_web/analysis_options.yaml b/packages/cross_file/cross_file_web/analysis_options.yaml deleted file mode 100644 index a5744c1cfbe7..000000000000 --- a/packages/cross_file/cross_file_web/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 5a10e7aa04ff..0a1efc6f88aa 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -1,2 +1,11 @@ -export 'src/web_cross_file.dart' show WebXFileExtension, WebXFileCreationParams; +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + export 'src/cross_file_web.dart'; +export 'src/web_cross_file.dart' + show + BlobWebXFileCreationParams, + UrlWebXFileCreationParams, + WebXFileCreationParams, + WebXFileExtension; diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart index 4951f10600ea..d1dcfb0f8c74 100644 --- a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -1,8 +1,14 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'web_cross_file.dart'; +/// Implementation of [CrossFilePlatform] for web. base class CrossFileWeb extends CrossFilePlatform { + /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileWeb(); } diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index 6673a5209476..b9710252e8da 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -1,24 +1,59 @@ -import 'dart:convert'; - -import 'dart:typed_data'; +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -import 'package:web/web.dart'; +import 'dart:convert'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; +import 'package:web/web.dart'; import 'web_helpers.dart'; -base class WebXFileCreationParams extends PlatformXFileCreationParams { - WebXFileCreationParams({required super.path, this.blob}); +/// Base implementation of [PlatformXFileCreationParams] for web. +@immutable +sealed class WebXFileCreationParams extends PlatformXFileCreationParams { + /// Constructs a [WebXFileCreationParams]. + const WebXFileCreationParams({required super.uri}); +} + +/// Implementation of [WebXFileCreationParams] with an object url. +@immutable +base class UrlWebXFileCreationParams extends WebXFileCreationParams { + /// Constructs a [UrlWebXFileCreationParams]. + const UrlWebXFileCreationParams({required String objectUrl}) + : super(uri: objectUrl); +} + +/// Implementation of [WebXFileCreationParams] with a [Blob]. +@immutable +base class BlobWebXFileCreationParams extends WebXFileCreationParams { + /// Constructs a [BlobWebXFileCreationParams]. + BlobWebXFileCreationParams(this.blob, {this.autoRevokeObjectUrl = true}) + : super(uri: URL.createObjectURL(blob)) { + if (autoRevokeObjectUrl) { + _finalizer.attach(this, uri); + } + } - final Blob? blob; + static final Finalizer _finalizer = Finalizer((String objectUrl) { + URL.revokeObjectURL(objectUrl); + }); + + /// The raw data represented by a [WebXFile]. + final Blob blob; + + /// Whether the object url obtained from [blob] should be revoked when this + /// instance is garbage collected. + final bool autoRevokeObjectUrl; } +/// Implementation of [PlatformXFile] for web. base class WebXFile extends PlatformXFile with WebXFileExtension { + /// Constructs a [WebXFile]. WebXFile(super.params) : super.implementation(); Blob? _cachedBlob; - final DateTime defaultLastModified = DateTime.now(); @override PlatformXFileExtension? get extension => this; @@ -27,10 +62,14 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { late final WebXFileCreationParams params = super.params is WebXFileCreationParams ? super.params as WebXFileCreationParams - : WebXFileCreationParams(path: params.path); + : UrlWebXFileCreationParams(objectUrl: params.uri); + @override Future getBlob() async { - return _cachedBlob ??= params.blob ?? await fetchBlob(params.path); + return _cachedBlob ??= switch (params) { + UrlWebXFileCreationParams() => await fetchBlob(params.uri), + final BlobWebXFileCreationParams params => params.blob, + }; } @override @@ -53,7 +92,7 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { return DateTime.fromMillisecondsSinceEpoch(blob.lastModified); } - return defaultLastModified; + return DateTime.now(); } @override @@ -89,12 +128,15 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { name = blob.name; } - await downloadBlob(blob, name); + downloadObjectUrl(params.uri, name); } } +/// Provides platform specific features for [WebXFile]. mixin WebXFileExtension implements PlatformXFileExtension { + /// The raw data represented by a [WebXFile]. Future getBlob(); + /// Attempts to download a [Blob], with [suggestedName] as the filename. Future download([String? suggestedName]); } diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index b967f3b9a173..7ad0a513e6d7 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -51,31 +51,14 @@ void downloadObjectUrl(String objectUrl, String? name) { addElementToContainerAndClick(target, element); } -/// Attempts to download a [blob], suggesting [name] as the filename. -/// -/// This method creates (and attempts to cleanup) an `objectUrl` for the given -/// [blob]. Since there's no way to know when the cleanup needs to happen, the -/// `blob` will seem to "leak" for about 5 minutes, until the `objectUrl` created -/// by this method is actually cleared. -Future downloadBlob(Blob blob, String? name) async { - final String objectUrl = URL.createObjectURL(blob); - // TODO(dit): Is there a better way to revoke the URL that we're creating? - Future.delayed(const Duration(minutes: 5), () { - // Is this the industry standard? - // See: https://github.com/eligrey/FileSaver.js/blob/cea522bc41bfadc364837293d0c4dc585a65ac46/src/FileSaver.js#L163 - URL.revokeObjectURL(objectUrl); - }); - downloadObjectUrl(objectUrl, name); -} - /// Converts a [Blob] to [Uint8List] through a [FileReader]. Future blobToBytes(Blob blob) async { - final FileReader reader = FileReader(); + final reader = FileReader(); reader.readAsArrayBuffer(blob); await reader.onLoadEnd.first; - final Uint8List? result = - (reader.result as JSArrayBuffer?)?.toDart.asUint8List(); + final Uint8List? result = (reader.result as JSArrayBuffer?)?.toDart + .asUint8List(); if (result == null) { throw Exception('Cannot read bytes from Blob. Is it still available?'); } @@ -99,4 +82,4 @@ Future fetchBlob(String objectUrl) async { } catch (e) { throw Exception('Could not fetch Blob by URL: $objectUrl'); } -} \ No newline at end of file +} diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 5d00a548afd6..9268d4643826 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -1,9 +1,8 @@ name: cross_file_web description: A Flutter plugin that provides a WebView widget on web. -repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_web -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 +repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_web +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 -publish_to: none environment: sdk: ^3.8.0 From 5bca2df0d4d4be204ad4046c930fed4c95a66730 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 18 Dec 2025 17:54:05 -0500 Subject: [PATCH 042/398] add extra space --- .../lib/src/android_cross_shared_storage_file.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart b/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart index 715516f9eb98..1bfab5193458 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart @@ -48,6 +48,7 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { start ?? 0, ); bytesToRead -= response.returnValue; + while (response.returnValue != -1 && bytesToRead > 0) { yield response.bytes; response = await inputStream.readBytes( From a8a19da75e81582e92fbc323079c192e7b7f72be Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 12:21:27 -0500 Subject: [PATCH 043/398] create example app for file --- .../plugin_integration_test.dart | 29 +++--- .../cross_file_android/example/lib/main.dart | 97 ++++++++++++++++--- .../cross_file_android/example/pubspec.yaml | 78 ++------------- 3 files changed, 109 insertions(+), 95 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart index ab1e84facf3a..7a43ba37cc41 100644 --- a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart +++ b/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart @@ -1,24 +1,23 @@ -// This is a basic Flutter integration test. -// -// Since integration tests run in a full Flutter application, they can interact -// with the host side of a plugin implementation, unlike Dart unit tests. -// -// For more information about Flutter integration tests, please see -// https://flutter.dev/to/integration-testing +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'package:cross_file_android_example/main.dart' as app; +import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:cross_file_android/cross_file_android.dart'; +/// Entry point for integration tests that require espresso. +@pragma('vm:entry-point') +void integrationTestMain() { + enableFlutterDriverExtension(); + app.main(); +} void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('getPlatformVersion test', (WidgetTester tester) async { - final CrossFileAndroid plugin = CrossFileAndroid(); - final String? version = await plugin.getPlatformVersion(); - // The version string depends on the host platform running the test, so - // just assert that some non-empty string is returned. - expect(version?.isNotEmpty, true); - }); + // Since this test is lacking integration tests, this test ensures the example + // app can be launched on an emulator/device. + testWidgets('Launch Test', (WidgetTester tester) async {}); } diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index b5079f60b5e8..5db553eda853 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -1,31 +1,104 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_driver/driver_extension.dart'; +import 'package:mime/mime.dart' as mime; + +/// Entry point for integration tests that require espresso. +@pragma('vm:entry-point') +void integrationTestMain() { + enableFlutterDriverExtension(); + main(); +} void main() { runApp(const MyApp()); } -class MyApp extends StatefulWidget { +class MyApp extends StatelessWidget { const MyApp({super.key}); - @override - State createState() => _MyAppState(); -} + Future _openFile(BuildContext context) async { + final XFile? file = await openFile(); + + if (!context.mounted) { + return; + } -class _MyAppState extends State { - String _platformVersion = 'Unknown'; + if (file case final XFile file) { + switch (mime.lookupMimeType(file.path)) { + case final String mimeType when mimeType.startsWith('text'): + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(file), + ); + case final String mimeType when mimeType.startsWith('image'): + case final String mimeType when mimeType.startsWith('application'): + case null: + debugPrint('Unsupported file type: ${file.path}'); + return; + } + } + } @override - void initState() { - super.initState(); + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Open a File')), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ], + ), + ), + ); } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.file, {super.key}); + + /// The file. + final XFile file; @override Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar(title: const Text('Plugin example app')), - body: Center(child: Text('Running on: $_platformVersion\n')), + return AlertDialog( + title: Text(file.path), + content: Scrollbar( + child: SingleChildScrollView( + child: FutureBuilder( + future: file.readAsString(), + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!); + } else { + return const CircularProgressIndicator(); + } + }, + ), + ), ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], ); } } diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index fd16bbfd3e0f..06ee82882e02 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -1,85 +1,27 @@ name: cross_file_android_example description: "Demonstrates how to use the cross_file_android plugin." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: - sdk: ^3.10.0-200.0.dev + sdk: ^3.9.0 + flutter: ">=3.35.0" -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: + file_selector: ^1.1.0 flutter: sdk: flutter - + flutter_driver: + sdk: flutter cross_file_android: - # When depending on this package from a real application you should use: - # cross_file_android: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 + mime: ^2.0.0 + video_player: ^2.8.6 dev_dependencies: - integration_test: - sdk: flutter flutter_test: sdk: flutter + integration_test: + sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package + uses-material-design: true \ No newline at end of file From b16163b4de61479e5260e915329944861fae6d17 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 12:37:14 -0500 Subject: [PATCH 044/398] fix app --- .../cross_file_android/example/lib/main.dart | 10 +++++----- .../cross_file_android/example/test/widget_test.dart | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 5db553eda853..16295cb199c1 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -15,11 +15,11 @@ void integrationTestMain() { } void main() { - runApp(const MyApp()); + runApp(MaterialApp(home: FileOpenScreen())); } -class MyApp extends StatelessWidget { - const MyApp({super.key}); +class FileOpenScreen extends StatelessWidget { + const FileOpenScreen({super.key}); Future _openFile(BuildContext context) async { final XFile? file = await openFile(); @@ -47,7 +47,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File')), + appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue,), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -83,7 +83,7 @@ class TextDisplay extends StatelessWidget { child: SingleChildScrollView( child: FutureBuilder( future: file.readAsString(), - builder: (BuildContext context, AsyncSnapshot snapshot) { + builder: (_, AsyncSnapshot snapshot) { if (snapshot.hasData) { return Text(snapshot.data!); } else { diff --git a/packages/cross_file/cross_file_android/example/test/widget_test.dart b/packages/cross_file/cross_file_android/example/test/widget_test.dart index 0cbf4761df4a..3c80a342f73a 100644 --- a/packages/cross_file/cross_file_android/example/test/widget_test.dart +++ b/packages/cross_file/cross_file_android/example/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:cross_file_android_example/main.dart'; void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); + await tester.pumpWidget(const FileOpenScreen()); // Verify that platform version is retrieved. expect( From 91087f24bb9c0eb907f30a1317c0f8e93439c246 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:07:40 -0500 Subject: [PATCH 045/398] cross file io readme update --- packages/cross_file/cross_file_io/README.md | 42 ++++--------------- .../cross_file/cross_file_io/pubspec.yaml | 6 +-- 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/packages/cross_file/cross_file_io/README.md b/packages/cross_file/cross_file_io/README.md index 4a260d8d279a..2dd438a8e28d 100644 --- a/packages/cross_file/cross_file_io/README.md +++ b/packages/cross_file/cross_file_io/README.md @@ -1,39 +1,15 @@ - - -TODO: Put a short description of the package here that helps potential users -know whether this package might be useful for them. - -## Features - -TODO: List what your package can do. Maybe include images, gifs, or videos. - -## Getting started - -TODO: List prerequisites and provide or point to information on how to -start using the package. +The `dart:io` implementation of [`cross_file`][1]. ## Usage -TODO: Include short and useful examples for package users. Add longer examples -to `/example` folder. - -```dart -const like = 'sample'; -``` +This package is [endorsed][2], which means you can simply use `cross_file` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. -## Additional information +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. -TODO: Tell users more about the package: where to find more information, how to -contribute to the package, how to file issues, what response they can expect -from the package authors, and more. +[1]: https://pub.dev/packages/cross_file +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index 922b0924095f..d00cebceb58f 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -9,15 +9,15 @@ environment: flutter: ">=3.35.0" dependencies: - flutter: - sdk: flutter cross_file_platform_interface: path: ../cross_file_platform_interface + flutter: + sdk: flutter dev_dependencies: - path: ^1.9.1 flutter_test: sdk: flutter + path: ^1.9.1 topics: - files From 58813fa0d58193b3eb8fee2240efe91fb809fa61 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 13:14:01 -0500 Subject: [PATCH 046/398] update java version --- .../cross_file/cross_file_android/android/.gitignore | 9 --------- .../cross_file_android/android/build.gradle | 11 +++++------ 2 files changed, 5 insertions(+), 15 deletions(-) delete mode 100644 packages/cross_file/cross_file_android/android/.gitignore diff --git a/packages/cross_file/cross_file_android/android/.gitignore b/packages/cross_file/cross_file_android/android/.gitignore deleted file mode 100644 index 161bdcdaf88c..000000000000 --- a/packages/cross_file/cross_file_android/android/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures -.cxx diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle index 70684cf06378..47abd56c2de0 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle +++ b/packages/cross_file/cross_file_android/android/build.gradle @@ -1,5 +1,5 @@ group = "dev.flutter.packages.cross_file_android" -version = "1.0-SNAPSHOT" +version = "1.0" buildscript { ext.kotlin_version = "2.1.0" @@ -26,16 +26,15 @@ apply plugin: "kotlin-android" android { namespace = "dev.flutter.packages.cross_file_android" - - compileSdk = 36 + compileSdk = flutter.compileSdkVersion compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = JavaVersion.VERSION_11 + jvmTarget = JavaVersion.VERSION_17.toString() } sourceSets { From 5b4b0fea32d781cb3818b23f445efb2301f3c712 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 14:04:05 -0500 Subject: [PATCH 047/398] update gradle to standard --- .../cross_file_android/android/build.gradle | 12 ++++- .../cross_file_android/example/.gitignore | 45 ------------------- .../example/analysis_options.yaml | 28 ------------ .../example/android/.gitignore | 14 ------ .../example/android/app/build.gradle.kts | 17 +++---- .../MainActivityTest.kt | 17 +++++++ .../android/app/src/debug/AndroidManifest.xml | 13 ++++++ .../DriverExtensionActivity.kt | 10 +++++ .../io/flutter/plugins/DartIntegrationTest.kt | 16 +++++++ .../example/android/build.gradle.kts | 24 ++++++++++ .../example/test/widget_test.dart | 27 ----------- 11 files changed, 99 insertions(+), 124 deletions(-) delete mode 100644 packages/cross_file/cross_file_android/example/.gitignore delete mode 100644 packages/cross_file/cross_file_android/example/analysis_options.yaml delete mode 100644 packages/cross_file/cross_file_android/example/android/.gitignore create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/DriverExtensionActivity.kt create mode 100644 packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt delete mode 100644 packages/cross_file/cross_file_android/example/test/widget_test.dart diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle index 47abd56c2de0..c5f6da0c3c38 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle +++ b/packages/cross_file/cross_file_android/android/build.gradle @@ -48,14 +48,22 @@ android { dependencies { implementation "androidx.documentfile:documentfile:1.1.0" + testImplementation("junit:junit:4.13.2") testImplementation("org.jetbrains.kotlin:kotlin-test") - testImplementation("org.mockito:mockito-core:5.0.0") + testImplementation("org.mockito.kotlin:mockito-kotlin:6.1.0") + testImplementation("org.mockito:mockito-inline:5.2.0") + testImplementation("androidx.test:core:1.7.0") + } + + lint { + checkAllWarnings = true + warningsAsErrors = true + disable 'AndroidGradlePluginVersion', 'InvalidPackage', 'GradleDependency', 'NewerVersionAvailable' } testOptions { unitTests.all { useJUnitPlatform() - testLogging { events "passed", "skipped", "failed", "standardOut", "standardError" outputs.upToDateWhen {false} diff --git a/packages/cross_file/cross_file_android/example/.gitignore b/packages/cross_file/cross_file_android/example/.gitignore deleted file mode 100644 index 3820a95c65c3..000000000000 --- a/packages/cross_file/cross_file_android/example/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/packages/cross_file/cross_file_android/example/analysis_options.yaml b/packages/cross_file/cross_file_android/example/analysis_options.yaml deleted file mode 100644 index 0d2902135cae..000000000000 --- a/packages/cross_file/cross_file_android/example/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_android/example/android/.gitignore b/packages/cross_file/cross_file_android/example/android/.gitignore deleted file mode 100644 index be3943c96d8e..000000000000 --- a/packages/cross_file/cross_file_android/example/android/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java -.cxx/ - -# Remember to never publicly share your keystore. -# See https://flutter.dev/to/reference-keystore -key.properties -**/*.keystore -**/*.jks diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts index 28a028671da1..c2318341720f 100644 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -11,19 +11,22 @@ android { ndkVersion = flutter.ndkVersion compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { - jvmTarget = JavaVersion.VERSION_11.toString() + jvmTarget = JavaVersion.VERSION_17.toString() + } + + sourceSets { + getByName("main") { + java.srcDirs("src/main/kotlin") + } } defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId = "dev.flutter.packages.cross_file_android_example" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode @@ -32,8 +35,6 @@ android { buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. signingConfig = signingConfigs.getByName("debug") } } diff --git a/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt b/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt new file mode 100644 index 000000000000..a2e2b13340c6 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt @@ -0,0 +1,17 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android_example + +import androidx.test.rule.ActivityTestRule +import dev.flutter.plugins.integration_test.FlutterTestRunner +import io.flutter.plugins.DartIntegrationTest +import org.junit.Rule +import org.junit.runner.RunWith + +@DartIntegrationTest +@RunWith(FlutterTestRunner::class) +class MainActivityTest { + @JvmField @Rule var rule = ActivityTestRule(MainActivity::class.java) +} diff --git a/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml b/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml index 399f6981d5d3..6601c9953612 100644 --- a/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml @@ -4,4 +4,17 @@ to allow setting breakpoints, to provide hot reload, etc. --> + + + + + diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/DriverExtensionActivity.kt b/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/DriverExtensionActivity.kt new file mode 100644 index 000000000000..02f48723a431 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_android_example/DriverExtensionActivity.kt @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android_example + +import io.flutter.embedding.android.FlutterActivity + +/** Test Activity that sets the name of the Dart method entrypoint in the manifest. */ +class DriverExtensionActivity : FlutterActivity() diff --git a/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt b/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt new file mode 100644 index 000000000000..5d0a4557390d --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt @@ -0,0 +1,16 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins + +/* + * Annotation to aid repository tooling in determining if a test is + * a native java unit test or a java class with a dart integration. + * + * See: https://github.com/flutter/flutter/blob/master/docs/ecosystem/testing/Plugin-Tests.md#enabling-android-ui-tests + * for more information. + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) +annotation class DartIntegrationTest diff --git a/packages/cross_file/cross_file_android/example/android/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/build.gradle.kts index dbee657bb5b9..c18b487fd40a 100644 --- a/packages/cross_file/cross_file_android/example/android/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/build.gradle.kts @@ -22,3 +22,27 @@ subprojects { tasks.register("clean") { delete(rootProject.layout.buildDirectory) } + +allprojects { + repositories { + // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. + val artifactRepoKey = "ARTIFACT_HUB_REPOSITORY" + val artifactRepoUrl = System.getenv(artifactRepoKey) + + if (artifactRepoUrl != null) { + println("Using artifact hub") + maven { url = uri(artifactRepoUrl) } + } + + google() + mavenCentral() + } +} + +gradle.projectsEvaluated { + project(":cross_file_android") { + tasks.withType { + options.compilerArgs.addAll(listOf("-Xlint:all", "-Werror")) + } + } +} diff --git a/packages/cross_file/cross_file_android/example/test/widget_test.dart b/packages/cross_file/cross_file_android/example/test/widget_test.dart deleted file mode 100644 index 3c80a342f73a..000000000000 --- a/packages/cross_file/cross_file_android/example/test/widget_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:cross_file_android_example/main.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const FileOpenScreen()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is Text && widget.data!.startsWith('Running on:'), - ), - findsOneWidget, - ); - }); -} From 572011e72f73d27d74c3cc85047afbb60af2a6c4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 21:16:30 -0500 Subject: [PATCH 048/398] add missing android resources for tests lolololol --- .../cross_file_android/android/build.gradle | 10 +- .../src/test/kotlin/android/net/Uri.kt | 22 +++ .../CrossFileAndroidPluginTest.kt | 27 ---- .../TestProxyApiRegistrar.kt | 9 ++ .../proxies/ContentResolverTest.kt | 10 +- .../proxies/DocumentFileTest.kt | 152 +++++++++--------- .../InputStreamReadBytesResponseTest.kt | 70 ++++---- .../proxies/InputStreamTest.kt | 74 ++++----- .../example/android/app/build.gradle.kts | 21 +++ .../gradle/wrapper/gradle-wrapper.properties | 2 +- 10 files changed, 215 insertions(+), 182 deletions(-) create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt delete mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt create mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle index c5f6da0c3c38..2a720168e497 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle +++ b/packages/cross_file/cross_file_android/android/build.gradle @@ -2,14 +2,14 @@ group = "dev.flutter.packages.cross_file_android" version = "1.0" buildscript { - ext.kotlin_version = "2.1.0" + ext.kotlin_version = "2.2.21" repositories { google() mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.9.1") + classpath("com.android.tools.build:gradle:8.13.1") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") } } @@ -47,7 +47,9 @@ android { } dependencies { - implementation "androidx.documentfile:documentfile:1.1.0" + implementation("androidx.documentfile:documentfile:1.1.0") + implementation("androidx.annotation:annotation:1.9.1") + implementation("androidx.core:core-ktx:1.13.0") testImplementation("junit:junit:4.13.2") testImplementation("org.jetbrains.kotlin:kotlin-test") testImplementation("org.mockito.kotlin:mockito-kotlin:6.1.0") @@ -62,6 +64,8 @@ android { } testOptions { + unitTests.includeAndroidResources = true + unitTests.returnDefaultValues = true unitTests.all { useJUnitPlatform() testLogging { diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt new file mode 100644 index 000000000000..c500e83da0be --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package android.net + +/** + * Redeclaration of Uri that works for tests. + * + * Without this redeclaration, `Uri.parse` always returns null. + */ +class Uri { + companion object { + @JvmStatic var lastValue: String? = null + + @JvmStatic + fun parse(value: String): Uri { + lastValue = value + return Uri() + } + } +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt deleted file mode 100644 index 9a0ffc7bca82..000000000000 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPluginTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package dev.flutter.packages.cross_file_android - -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import kotlin.test.Test -import org.mockito.Mockito - -/* - * This demonstrates a simple unit test of the Kotlin portion of this plugin's implementation. - * - * Once you have built the plugin's example app, you can run these tests from the command - * line by running `./gradlew testDebugUnitTest` in the `example/android/` directory, or - * you can run them directly from IDEs that support JUnit such as Android Studio. - */ - -internal class CrossFileAndroidPluginTest { - @Test - fun onMethodCall_getPlatformVersion_returnsExpectedValue() { - val plugin = CrossFileAndroidPlugin() - - val call = MethodCall("getPlatformVersion", null) - val mockResult: MethodChannel.Result = Mockito.mock(MethodChannel.Result::class.java) - plugin.onMethodCall(call, mockResult) - - Mockito.verify(mockResult).success("Android " + android.os.Build.VERSION.RELEASE) - } -} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt new file mode 100644 index 000000000000..7c822fe396e6 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt @@ -0,0 +1,9 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android + +import org.mockito.kotlin.mock + +class TestProxyApiRegistrar : ProxyApiRegistrar(mock(), mock()) \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt index 97c1f2f9d225..98cb6c8edbfb 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt @@ -5,6 +5,9 @@ package dev.flutter.packages.cross_file_android.proxies import android.content.ContentResolver +import android.os.Looper +import androidx.core.net.toUri +import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals @@ -14,13 +17,14 @@ import org.mockito.kotlin.whenever class ContentResolverTest { @Test fun openInputStream() { - val api = TestProxyApiRegistrar().getPigeonApiContentResolver() + val a = Looper.getMainLooper() + val api = TestProxyApiRegistrar()//.getPigeonApiContentResolver() val instance = mock() val uri = "myString" val value = mock() - whenever(instance.openInputStream(uri)).thenReturn(value) + whenever(instance.openInputStream(uri.toUri())).thenReturn(value) - assertEquals(value, api.openInputStream(instance, uri)) + assertEquals(value, api.openInputStream(instance, uri)) } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt index 3a4940a99bd9..9dd592bee6c5 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -1,76 +1,76 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import androidx.documentfile.provider.DocumentFile -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever - -class DocumentFileTest { - @Test - fun fromSingleUri() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - assertTrue(api.fromSingleUri("myString") is DocumentFileProxyApi.DocumentFile) - } - - @Test - fun canRead() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = true - whenever(instance.canRead()).thenReturn(value) - - assertEquals(value, api.canRead(instance)) - } - - @Test - fun delete() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = true - whenever(instance.delete()).thenReturn(value) - - assertEquals(value, api.delete(instance)) - } - - @Test - fun exists() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = true - whenever(instance.exists()).thenReturn(value) - - assertEquals(value, api.exists(instance)) - } - - @Test - fun lastModified() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = 0 - whenever(instance.lastModified()).thenReturn(value) - - assertEquals(value, api.lastModified(instance)) - } - - @Test - fun length() { - val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() - - val instance = mock() - val value = 0 - whenever(instance.length()).thenReturn(value) - - assertEquals(value, api.length(instance)) - } -} +//// Copyright 2013 The Flutter Authors. All rights reserved. +//// Use of this source code is governed by a BSD-style license that can be +//// found in the LICENSE file. +// +//package dev.flutter.packages.cross_file_android.proxies +// +//import androidx.documentfile.provider.DocumentFile +//import kotlin.test.Test +//import kotlin.test.assertEquals +//import kotlin.test.assertTrue +//import org.mockito.kotlin.mock +//import org.mockito.kotlin.whenever +// +//class DocumentFileTest { +// @Test +// fun fromSingleUri() { +// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() +// +// assertTrue(api.fromSingleUri("myString") is DocumentFileProxyApi.DocumentFile) +// } +// +// @Test +// fun canRead() { +// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() +// +// val instance = mock() +// val value = true +// whenever(instance.canRead()).thenReturn(value) +// +// assertEquals(value, api.canRead(instance)) +// } +// +// @Test +// fun delete() { +// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() +// +// val instance = mock() +// val value = true +// whenever(instance.delete()).thenReturn(value) +// +// assertEquals(value, api.delete(instance)) +// } +// +// @Test +// fun exists() { +// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() +// +// val instance = mock() +// val value = true +// whenever(instance.exists()).thenReturn(value) +// +// assertEquals(value, api.exists(instance)) +// } +// +// @Test +// fun lastModified() { +// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() +// +// val instance = mock() +// val value = 0 +// whenever(instance.lastModified()).thenReturn(value) +// +// assertEquals(value, api.lastModified(instance)) +// } +// +// @Test +// fun length() { +// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() +// +// val instance = mock() +// val value = 0 +// whenever(instance.length()).thenReturn(value) +// +// assertEquals(value, api.length(instance)) +// } +//} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt index 7e3c46dde5e3..e6bb57dd2b53 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt @@ -1,35 +1,35 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -import kotlin.test.Test -import kotlin.test.assertEquals -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever - -class InputStreamReadBytesResponseTest { - @Test - fun returnValue() { - val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() - - val instance = mock() - val value = 0 - whenever(instance.returnValue).thenReturn(value) - - assertEquals(value, api.returnValue(instance)) - } - - @Test - fun bytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() - - val instance = mock() - val value = byteArrayOf(0xA1.toByte()) - whenever(instance.bytes).thenReturn(value) - - assertEquals(value, api.bytes(instance)) - } -} +//// Copyright 2013 The Flutter Authors. All rights reserved. +//// Use of this source code is governed by a BSD-style license that can be +//// found in the LICENSE file. +// +//package dev.flutter.packages.cross_file_android.proxies +// +//import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +//import kotlin.test.Test +//import kotlin.test.assertEquals +//import org.mockito.kotlin.mock +//import org.mockito.kotlin.whenever +// +//class InputStreamReadBytesResponseTest { +// @Test +// fun returnValue() { +// val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() +// +// val instance = mock() +// val value = 0 +// whenever(instance.returnValue).thenReturn(value) +// +// assertEquals(value, api.returnValue(instance)) +// } +// +// @Test +// fun bytes() { +// val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() +// +// val instance = mock() +// val value = byteArrayOf(0xA1.toByte()) +// whenever(instance.bytes).thenReturn(value) +// +// assertEquals(value, api.bytes(instance)) +// } +//} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index ad955044dbf1..7349af9c3f5f 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -1,37 +1,37 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -import java.io.InputStream -import kotlin.test.Test -import kotlin.test.assertEquals -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever - -class InputStreamTest { - @Test - fun readBytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStream() - - val instance = mock() - val len = 0 - val value = mock() - whenever(instance.readBytes(len)).thenReturn(value) - - assertEquals(value, api.readBytes(instance, len)) - } - - @Test - fun readAllBytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStream() - - val instance = mock() - val value = byteArrayOf(0xA1.toByte()) - whenever(instance.readAllBytes()).thenReturn(value) - - assertEquals(value, api.readAllBytes(instance)) - } -} +//// Copyright 2013 The Flutter Authors. All rights reserved. +//// Use of this source code is governed by a BSD-style license that can be +//// found in the LICENSE file. +// +//package dev.flutter.packages.cross_file_android.proxies +// +//import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +//import java.io.InputStream +//import kotlin.test.Test +//import kotlin.test.assertEquals +//import org.mockito.kotlin.mock +//import org.mockito.kotlin.whenever +// +//class InputStreamTest { +// @Test +// fun readBytes() { +// val api = TestProxyApiRegistrar().getPigeonApiInputStream() +// +// val instance = mock() +// val len = 0 +// val value = mock() +// whenever(instance.readBytes(len)).thenReturn(value) +// +// assertEquals(value, api.readBytes(instance, len)) +// } +// +// @Test +// fun readAllBytes() { +// val api = TestProxyApiRegistrar().getPigeonApiInputStream() +// +// val instance = mock() +// val value = byteArrayOf(0xA1.toByte()) +// whenever(instance.readAllBytes()).thenReturn(value) +// +// assertEquals(value, api.readAllBytes(instance)) +// } +//} diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts index c2318341720f..e019b79077ea 100644 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -1,3 +1,5 @@ +import java.util.Properties + plugins { id("com.android.application") id("kotlin-android") @@ -5,6 +7,18 @@ plugins { id("dev.flutter.flutter-gradle-plugin") } +val localProperties = Properties() +val localPropertiesFile = rootProject.file("local.properties") + +if (localPropertiesFile.exists()) { + localPropertiesFile.reader(Charsets.UTF_8).use { reader -> + localProperties.load(reader) + } +} + +val flutterVersionCode: String = localProperties.getProperty("flutter.versionCode") ?: "1" +val flutterVersionName: String = localProperties.getProperty("flutter.versionName") ?: "1.0" + android { namespace = "dev.flutter.packages.cross_file_android_example" compileSdk = flutter.compileSdkVersion @@ -40,6 +54,13 @@ android { } } +dependencies { + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test:runner:1.2.0") + androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") + api("androidx.test:core:1.4.0") +} + flutter { source = "../.." } diff --git a/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties index ac3b47926ee5..02767eb1ca47 100644 --- a/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip From c89464502a41e08aef4a0af7ac04c3d2eae79fff Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 22:35:35 -0500 Subject: [PATCH 049/398] fix unit tests --- .../proxies/ContentResolverTest.kt | 10 +- .../proxies/DocumentFileTest.kt | 167 ++++++++++-------- .../InputStreamReadBytesResponseTest.kt | 71 ++++---- .../proxies/InputStreamTest.kt | 85 +++++---- 4 files changed, 181 insertions(+), 152 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt index 98cb6c8edbfb..06df65a80651 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt @@ -5,9 +5,11 @@ package dev.flutter.packages.cross_file_android.proxies import android.content.ContentResolver +import android.net.Uri import android.os.Looper import androidx.core.net.toUri import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import org.mockito.kotlin.any import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals @@ -17,14 +19,14 @@ import org.mockito.kotlin.whenever class ContentResolverTest { @Test fun openInputStream() { - val a = Looper.getMainLooper() - val api = TestProxyApiRegistrar()//.getPigeonApiContentResolver() + val api = TestProxyApiRegistrar().getPigeonApiContentResolver() val instance = mock() val uri = "myString" val value = mock() - whenever(instance.openInputStream(uri.toUri())).thenReturn(value) + whenever(instance.openInputStream(any())).thenReturn(value) - assertEquals(value, api.openInputStream(instance, uri)) + assertEquals(value, api.openInputStream(instance, uri)) + assertEquals(uri, Uri.lastValue) } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt index 9dd592bee6c5..026501e8d032 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -1,76 +1,91 @@ -//// Copyright 2013 The Flutter Authors. All rights reserved. -//// Use of this source code is governed by a BSD-style license that can be -//// found in the LICENSE file. -// -//package dev.flutter.packages.cross_file_android.proxies -// -//import androidx.documentfile.provider.DocumentFile -//import kotlin.test.Test -//import kotlin.test.assertEquals -//import kotlin.test.assertTrue -//import org.mockito.kotlin.mock -//import org.mockito.kotlin.whenever -// -//class DocumentFileTest { -// @Test -// fun fromSingleUri() { -// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() -// -// assertTrue(api.fromSingleUri("myString") is DocumentFileProxyApi.DocumentFile) -// } -// -// @Test -// fun canRead() { -// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() -// -// val instance = mock() -// val value = true -// whenever(instance.canRead()).thenReturn(value) -// -// assertEquals(value, api.canRead(instance)) -// } -// -// @Test -// fun delete() { -// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() -// -// val instance = mock() -// val value = true -// whenever(instance.delete()).thenReturn(value) -// -// assertEquals(value, api.delete(instance)) -// } -// -// @Test -// fun exists() { -// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() -// -// val instance = mock() -// val value = true -// whenever(instance.exists()).thenReturn(value) -// -// assertEquals(value, api.exists(instance)) -// } -// -// @Test -// fun lastModified() { -// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() -// -// val instance = mock() -// val value = 0 -// whenever(instance.lastModified()).thenReturn(value) -// -// assertEquals(value, api.lastModified(instance)) -// } -// -// @Test -// fun length() { -// val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() -// -// val instance = mock() -// val value = 0 -// whenever(instance.length()).thenReturn(value) -// -// assertEquals(value, api.length(instance)) -// } -//} +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import android.net.Uri +import androidx.documentfile.provider.DocumentFile +import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import org.mockito.Mockito +import org.mockito.Mockito.mockStatic +import org.mockito.kotlin.any +import org.mockito.kotlin.eq +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +class DocumentFileTest { + @Test + fun fromSingleUri() { + val registrar = TestProxyApiRegistrar() + val api = registrar.getPigeonApiDocumentFile() + + mockStatic(DocumentFile::class.java).use { mockedStatic -> + val instance = mock() + val singleUri = "myString" + mockedStatic.`when` { DocumentFile.fromSingleUri(eq(registrar.context), any()) } + .thenReturn(instance) + + assertEquals(instance, api.fromSingleUri(singleUri)) + assertEquals( singleUri, Uri.lastValue) + } + } + + @Test + fun canRead() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.canRead()).thenReturn(value) + + assertEquals(value, api.canRead(instance)) + } + + @Test + fun delete() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.delete()).thenReturn(value) + + assertEquals(value, api.delete(instance)) + } + + @Test + fun exists() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.exists()).thenReturn(value) + + assertEquals(value, api.exists(instance)) + } + + @Test + fun lastModified() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = 0L + whenever(instance.lastModified()).thenReturn(value) + + assertEquals(value, api.lastModified(instance)) + } + + @Test + fun length() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = 0L + whenever(instance.length()).thenReturn(value) + + assertEquals(value, api.length(instance)) + } +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt index e6bb57dd2b53..5540ca22376d 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt @@ -1,35 +1,36 @@ -//// Copyright 2013 The Flutter Authors. All rights reserved. -//// Use of this source code is governed by a BSD-style license that can be -//// found in the LICENSE file. -// -//package dev.flutter.packages.cross_file_android.proxies -// -//import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -//import kotlin.test.Test -//import kotlin.test.assertEquals -//import org.mockito.kotlin.mock -//import org.mockito.kotlin.whenever -// -//class InputStreamReadBytesResponseTest { -// @Test -// fun returnValue() { -// val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() -// -// val instance = mock() -// val value = 0 -// whenever(instance.returnValue).thenReturn(value) -// -// assertEquals(value, api.returnValue(instance)) -// } -// -// @Test -// fun bytes() { -// val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() -// -// val instance = mock() -// val value = byteArrayOf(0xA1.toByte()) -// whenever(instance.bytes).thenReturn(value) -// -// assertEquals(value, api.bytes(instance)) -// } -//} +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import kotlin.test.Test +import kotlin.test.assertEquals +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +class InputStreamReadBytesResponseTest { + @Test + fun returnValue() { + val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() + + val instance = mock() + val value = 0 + whenever(instance.returnValue).thenReturn(value) + + assertEquals(value.toLong(), api.returnValue(instance)) + } + + @Test + fun bytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() + + val instance = mock() + val value = byteArrayOf(0xA1.toByte()) + whenever(instance.bytes).thenReturn(value) + + assertEquals(value, api.bytes(instance)) + } +} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index 7349af9c3f5f..c0fc7c00f0fb 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -1,37 +1,48 @@ -//// Copyright 2013 The Flutter Authors. All rights reserved. -//// Use of this source code is governed by a BSD-style license that can be -//// found in the LICENSE file. -// -//package dev.flutter.packages.cross_file_android.proxies -// -//import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -//import java.io.InputStream -//import kotlin.test.Test -//import kotlin.test.assertEquals -//import org.mockito.kotlin.mock -//import org.mockito.kotlin.whenever -// -//class InputStreamTest { -// @Test -// fun readBytes() { -// val api = TestProxyApiRegistrar().getPigeonApiInputStream() -// -// val instance = mock() -// val len = 0 -// val value = mock() -// whenever(instance.readBytes(len)).thenReturn(value) -// -// assertEquals(value, api.readBytes(instance, len)) -// } -// -// @Test -// fun readAllBytes() { -// val api = TestProxyApiRegistrar().getPigeonApiInputStream() -// -// val instance = mock() -// val value = byteArrayOf(0xA1.toByte()) -// whenever(instance.readAllBytes()).thenReturn(value) -// -// assertEquals(value, api.readAllBytes(instance)) -// } -//} +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_android.proxies + +import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import org.mockito.ArgumentCaptor +import org.mockito.kotlin.any +import org.mockito.kotlin.capture +import org.mockito.kotlin.eq +import java.io.InputStream +import kotlin.test.Test +import kotlin.test.assertEquals +import org.mockito.kotlin.mock +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever +import java.io.ByteArrayInputStream + +class InputStreamTest { + @Test + fun readBytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val bytesCaptor = ArgumentCaptor.forClass(ByteArray::class.java) + val off = 1 + val len = 2 + val value = 3 + whenever(instance.read(bytesCaptor.capture(), eq(off), eq(len))).thenReturn(value) + + assertEquals(api.readBytes(instance, len.toLong(), off.toLong()), InputStreamReadBytesResponse(value, bytesCaptor.value)) + assertEquals(bytesCaptor.value.size, len) + } + + @Test + fun readAllBytes() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val value = byteArrayOf(0xA1.toByte()) + val instance = ByteArrayInputStream(value) + + val result = api.readAllBytes(instance) + assertEquals(value.size, result.size) + assertEquals(value.first(), result.first()) + } +} From eb1e656461c2ebc16d9205f5eeed9740166e169f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 23:49:13 -0500 Subject: [PATCH 050/398] finish all tests --- .../src/test/kotlin/android/net/Uri.kt | 11 ++-- .../proxies/ContentResolverTest.kt | 18 +++-- .../proxies/DocumentFileTest.kt | 66 +++++++++++++++++-- .../proxies/InputStreamTest.kt | 12 ++++ 4 files changed, 94 insertions(+), 13 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt index c500e83da0be..53b3b85d7811 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/android/net/Uri.kt @@ -9,14 +9,15 @@ package android.net * * Without this redeclaration, `Uri.parse` always returns null. */ -class Uri { +data class Uri(val uri: String) { companion object { - @JvmStatic var lastValue: String? = null - @JvmStatic fun parse(value: String): Uri { - lastValue = value - return Uri() + return Uri(value) } } + + override fun toString(): String { + return this.uri + } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt index 06df65a80651..f1742acfc98f 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt @@ -17,16 +17,26 @@ import org.mockito.kotlin.mock import org.mockito.kotlin.whenever class ContentResolverTest { + @Test + fun instance() { + val registrar = TestProxyApiRegistrar() + val api = registrar.getPigeonApiContentResolver() + + val instance = mock() + whenever(registrar.context.contentResolver).thenReturn(instance) + + assertEquals(instance, api.instance()) + } + @Test fun openInputStream() { val api = TestProxyApiRegistrar().getPigeonApiContentResolver() val instance = mock() - val uri = "myString" + val uri = Uri("myString") val value = mock() - whenever(instance.openInputStream(any())).thenReturn(value) + whenever(instance.openInputStream(uri)).thenReturn(value) - assertEquals(value, api.openInputStream(instance, uri)) - assertEquals(uri, Uri.lastValue) + assertEquals(value, api.openInputStream(instance, uri.toString())) } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt index 026501e8d032..a635297ddb6c 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -25,12 +25,26 @@ class DocumentFileTest { mockStatic(DocumentFile::class.java).use { mockedStatic -> val instance = mock() - val singleUri = "myString" - mockedStatic.`when` { DocumentFile.fromSingleUri(eq(registrar.context), any()) } + val singleUri = Uri("myString") + mockedStatic.`when` { DocumentFile.fromSingleUri(registrar.context, singleUri) } .thenReturn(instance) - assertEquals(instance, api.fromSingleUri(singleUri)) - assertEquals( singleUri, Uri.lastValue) + assertEquals(instance, api.fromSingleUri(singleUri.toString())) + } + } + + @Test + fun fromTreeUri() { + val registrar = TestProxyApiRegistrar() + val api = registrar.getPigeonApiDocumentFile() + + mockStatic(DocumentFile::class.java).use { mockedStatic -> + val instance = mock() + val treeUri = Uri("myString") + mockedStatic.`when` { DocumentFile.fromTreeUri(registrar.context, treeUri) } + .thenReturn(instance) + + assertEquals(instance, api.fromTreeUri(treeUri.toString())) } } @@ -88,4 +102,48 @@ class DocumentFileTest { assertEquals(value, api.length(instance)) } + + @Test + fun isFile() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.isFile).thenReturn(value) + + assertEquals(value, api.isFile(instance)) + } + + @Test + fun isDirectory() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = true + whenever(instance.isDirectory).thenReturn(value) + + assertEquals(value, api.isDirectory(instance)) + } + + @Test + fun listFiles() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = listOf(mock()) + whenever(instance.listFiles()).thenReturn(value.toTypedArray()) + + assertEquals(value, api.listFiles(instance)) + } + + @Test + fun getUri() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = Uri("myString") + whenever(instance.uri).thenReturn(value) + + assertEquals(value.toString(), api.getUri(instance)) + } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index c0fc7c00f0fb..17095aa19e4c 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -45,4 +45,16 @@ class InputStreamTest { assertEquals(value.size, result.size) assertEquals(value.first(), result.first()) } + + @Test + fun skip() { + val api = TestProxyApiRegistrar().getPigeonApiInputStream() + + val instance = mock() + val n = 5L + val value = 6L + whenever(instance.skip(n)).thenReturn(value) + + assertEquals(value, api.skip(instance, n)) + } } From 880a410ead12ab14c96b7dfc441a224214646c22 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 29 Dec 2025 23:49:48 -0500 Subject: [PATCH 051/398] formatting --- .../cross_file_android/ProxyApiRegistrar.kt | 6 +- .../proxies/AndroidLibrary.g.kt | 651 +++++++++++------- .../proxies/InputStreamProxyApi.kt | 6 +- .../TestProxyApiRegistrar.kt | 2 +- .../proxies/ContentResolverTest.kt | 3 - .../proxies/DocumentFileTest.kt | 16 +- .../proxies/InputStreamTest.kt | 14 +- .../cross_file_android/example/lib/main.dart | 5 +- .../lib/src/android_library.g.dart | 425 +++++++----- 9 files changed, 662 insertions(+), 466 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt index b6be27260d37..86d01a26826d 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -5,10 +5,6 @@ package dev.flutter.packages.cross_file_android import android.content.Context -import android.os.Build -import android.os.Handler -import android.os.Looper -import androidx.annotation.ChecksSdkIntAtLeast import dev.flutter.packages.cross_file_android.proxies.AndroidLibraryPigeonProxyApiRegistrar import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi @@ -25,7 +21,7 @@ import io.flutter.plugin.common.BinaryMessenger * implementation and any additional resources needed by an implementation. */ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Context) : - AndroidLibraryPigeonProxyApiRegistrar(binaryMessenger) { + AndroidLibraryPigeonProxyApiRegistrar(binaryMessenger) { override fun getPigeonApiDocumentFile(): PigeonApiDocumentFile { return DocumentFileProxyApi(this) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index 267c71410226..50ac73ccd6c6 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -10,16 +10,17 @@ package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object AndroidLibraryPigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + return FlutterError( + "channel-error", "Unable to establish connection on channel: '$channelName'.", "") + } fun wrapResult(result: Any?): List { return listOf(result) @@ -27,50 +28,48 @@ private object AndroidLibraryPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() /** * Maintains instances used to communicate with the corresponding objects in Dart. * - * Objects stored in this container are represented by an object in Dart that is also stored in - * an InstanceManager with the same identifier. + * Objects stored in this container are represented by an object in Dart that is also stored in an + * InstanceManager with the same identifier. * * When an instance is added with an identifier, either can be used to retrieve the other. * - * Added instances are added as a weak reference and a strong reference. When the strong - * reference is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong - * reference is removed and then the identifier is retrieved with the intention to pass the identifier - * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance - * is recreated. The strong reference will then need to be removed manually again. + * Added instances are added as a weak reference and a strong reference. When the strong reference + * is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the + * strong reference is removed and then the identifier is retrieved with the intention to pass the + * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the + * instance is recreated. The strong reference will then need to be removed manually again. */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class AndroidLibraryPigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ +class AndroidLibraryPigeonInstanceManager( + private val finalizationListener: PigeonFinalizationListener +) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface PigeonFinalizationListener { fun onFinalize(identifier: Long) } @@ -139,19 +138,20 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige private const val tag = "PigeonInstanceManager" /** - * Instantiate a new manager with a listener for garbage collected weak - * references. + * Instantiate a new manager with a listener for garbage collected weak references. * * When the manager is no longer needed, [stopFinalizationListener] must be called. */ - fun create(finalizationListener: PigeonFinalizationListener): AndroidLibraryPigeonInstanceManager { + fun create( + finalizationListener: PigeonFinalizationListener + ): AndroidLibraryPigeonInstanceManager { return AndroidLibraryPigeonInstanceManager(finalizationListener) } } /** - * Removes `identifier` and return its associated strongly referenced instance, if present, - * from the manager. + * Removes `identifier` and return its associated strongly referenced instance, if present, from + * the manager. */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() @@ -161,15 +161,13 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Retrieves the identifier paired with an instance, if present, otherwise `null`. * - * * If the manager contains a strong reference to `instance`, it will return the identifier * associated with `instance`. If the manager contains only a weak reference to `instance`, a new * strong reference to `instance` will be added and will need to be removed again with [remove]. * - * * If this method returns a nonnull identifier, this method also expects the Dart - * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - * identifier is associated with. + * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart + * instance the identifier is associated with. */ fun getIdentifierForStrongReference(instance: Any?): Long? { logWarningIfFinalizationListenerHasStopped() @@ -186,9 +184,9 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Adds a new instance that was instantiated from Dart. * - * The same instance can be added multiple times, but each identifier must be unique. This - * allows two objects that are equivalent (e.g. the `equals` method returns true and their - * hashcodes are equal) to both be added. + * The same instance can be added multiple times, but each identifier must be unique. This allows + * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are + * equal) to both be added. * * [identifier] must be >= 0 and unique. */ @@ -200,13 +198,15 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Adds a new unique instance that was instantiated from the host platform. * - * If the manager contains [instance], this returns the corresponding identifier. If the - * manager does not contain [instance], this adds the instance and returns a unique - * identifier for that [instance]. + * If the manager contains [instance], this returns the corresponding identifier. If the manager + * does not contain [instance], this adds the instance and returns a unique identifier for that + * [instance]. */ fun addHostCreatedInstance(instance: Any): Long { logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } + require(!containsInstance(instance)) { + "Instance of ${instance.javaClass} has already been added." + } val identifier = nextIdentifier++ addInstance(instance, identifier) return identifier @@ -290,39 +290,43 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige private fun logWarningIfFinalizationListenerHasStopped() { if (hasFinalizationListenerStopped()) { Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped." - ) + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped.") } } } - /** Generated API for managing the Dart and native `InstanceManager`s. */ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { companion object { /** The codec used by AndroidLibraryPigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { - AndroidLibraryPigeonCodec() - } + val codec: MessageCodec by lazy { AndroidLibraryPigeonCodec() } /** * Sets up an instance of `AndroidLibraryPigeonInstanceManagerApi` to handle messages from the * `binaryMessenger`. */ - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: AndroidLibraryPigeonInstanceManager?) { + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + instanceManager: AndroidLibraryPigeonInstanceManager? + ) { run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", + codec) if (instanceManager != null) { channel.setMessageHandler { message, reply -> val args = message as List val identifierArg = args[0] as Long - val wrapped: List = try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -330,15 +334,20 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", + codec) if (instanceManager != null) { channel.setMessageHandler { _, reply -> - val wrapped: List = try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -348,9 +357,9 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) -{ - val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(identifierArg)) { if (it is List<*>) { @@ -361,13 +370,13 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } /** - * Provides implementations for each ProxyApi implementation and provides access to resources - * needed by any implementation. + * Provides implementations for each ProxyApi implementation and provides access to resources needed + * by any implementation. */ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { /** Whether APIs should ignore calling to Dart. */ @@ -384,24 +393,23 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary init { val api = AndroidLibraryPigeonInstanceManagerApi(binaryMessenger) - instanceManager = AndroidLibraryPigeonInstanceManager.create( - object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier" - ) - } - } - } - } - ) + instanceManager = + AndroidLibraryPigeonInstanceManager.create( + object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier") + } + } + } + }) } /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of - * `DocumentFile` to the Dart `InstanceManager`. + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` + * to the Dart `InstanceManager`. */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile @@ -418,8 +426,8 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of - * `InputStream` to the Dart `InstanceManager`. + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to + * the Dart `InstanceManager`. */ abstract fun getPigeonApiInputStream(): PigeonApiInputStream @@ -429,6 +437,7 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } + fun tearDown() { AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) @@ -436,17 +445,17 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } -private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibraryPigeonProxyApiRegistrar) : AndroidLibraryPigeonCodec() { + +private class AndroidLibraryPigeonProxyApiBaseCodec( + val registrar: AndroidLibraryPigeonProxyApiRegistrar +) : AndroidLibraryPigeonCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 128.toByte() -> { val identifier: Long = readValue(buffer) as Long val instance: Any? = registrar.instanceManager.getInstance(identifier) if (instance == null) { - Log.e( - "PigeonProxyApiBaseCodec", - "Failed to find instance with identifier: $identifier" - ) + Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") } return instance } @@ -455,16 +464,27 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { + if (value is Boolean || + value is ByteArray || + value is Double || + value is DoubleArray || + value is FloatArray || + value is Int || + value is IntArray || + value is List<*> || + value is Long || + value is LongArray || + value is Map<*, *> || + value is String || + value == null) { super.writeValue(stream, value) return } fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception" - ) + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception") } if (value is androidx.documentfile.provider.DocumentFile) { @@ -473,22 +493,19 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) } } - } - else if (value is android.content.ContentResolver) { + } else if (value is android.content.ContentResolver) { registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } - else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + } else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) } } - } - else if (value is java.io.InputStream) { + } else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) @@ -501,27 +518,33 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar stream.write(128) writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) } - else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") + else -> + throw IllegalArgumentException( + "Unsupported value: '$value' of type '${value.javaClass.name}'") } } } + private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } /** - * Representation of a document backed by either a - * android.provider.DocumentsProvider or a raw file on disk. + * Representation of a document backed by either a android.provider.DocumentsProvider or a raw file + * on disk. * * See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { +abstract class PigeonApiDocumentFile( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { /** Create a DocumentFile representing the single document at the given Uri. */ abstract fun fromSingleUri(singleUri: String): androidx.documentfile.provider.DocumentFile @@ -537,8 +560,8 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean /** - * Returns the time when this file was last modified, measured in - * milliseconds since January 1st, 1970, midnight. + * Returns the time when this file was last modified, measured in milliseconds since January 1st, + * 1970, midnight. */ abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long @@ -551,11 +574,10 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig /** Indicates if this file represents a *directory*. */ abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - /** - * Returns an list of files contained in the directory represented by this - * file. - */ - abstract fun listFiles(pigeon_instance: androidx.documentfile.provider.DocumentFile): List + /** Returns an list of files contained in the directory represented by this file. */ + abstract fun listFiles( + pigeon_instance: androidx.documentfile.provider.DocumentFile + ): List /** A Uri for the underlying document represented by this file. */ abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String @@ -565,18 +587,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val singleUriArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(singleUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromSingleUri(singleUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -584,18 +612,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val treeUriArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromTreeUri(treeUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromTreeUri(treeUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -603,16 +637,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -620,16 +659,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -637,16 +679,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -654,16 +699,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -671,16 +721,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -688,16 +741,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.isFile(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.isFile(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -705,16 +761,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.isDirectory(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.isDirectory(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -722,16 +783,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.listFiles(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.listFiles(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -739,16 +805,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.getUri(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getUri(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -760,16 +829,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" @@ -777,17 +849,17 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** * This class provides applications access to the content model. @@ -795,32 +867,40 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig * See https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * Helper field for accessing the `ContentResolver` from the current Android - * `Context`. - */ +abstract class PigeonApiContentResolver( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + /** Helper field for accessing the `ContentResolver` from the current Android `Context`. */ abstract fun instance(): android.content.ContentResolver /** Open a stream on to the content associated with a content URI. */ - abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? + abstract fun openInputStream( + pigeon_instance: android.content.ContentResolver, + uri: String + ): java.io.InputStream? companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -828,17 +908,22 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as android.content.ContentResolver val uriArg = args[1] as String - val wrapped: List = try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -850,16 +935,19 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: android.content.ContentResolver, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" @@ -867,71 +955,86 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** Return type for [InputStream.readBytes] that handles returning two values. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long +abstract class PigeonApiInputStreamReadBytesResponse( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + abstract fun returnValue( + pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + ): Long - abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray + abstract fun bytes( + pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + ): ByteArray @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) -{ + /** + * Creates a Dart instance of InputStreamReadBytesResponse and attaches it to + * [pigeon_instanceArg]. + */ + fun pigeon_newInstance( + pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val returnValueArg = returnValue(pigeon_instanceArg) val bytesArg = bytes(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channelName = + "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** - * This abstract class is the superclass of all classes representing an input - * stream of bytes. + * This abstract class is the superclass of all classes representing an input stream of bytes. * * See https://developer.android.com/reference/java/io/InputStream. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * Reads some number of bytes from the input stream and stores them into the - * returns them. - */ - abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long, off: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +abstract class PigeonApiInputStream( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + /** Reads some number of bytes from the input stream and stores them into the returns them. */ + abstract fun readBytes( + pigeon_instance: java.io.InputStream, + len: Long, + off: Long + ): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse /** Reads all remaining bytes from the input stream. */ abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray @@ -944,18 +1047,23 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val lenArg = args[1] as Long val offArg = args[2] as Long - val wrapped: List = try { - listOf(api.readBytes(pigeon_instanceArg, lenArg, offArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readBytes(pigeon_instanceArg, lenArg, offArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -963,16 +1071,21 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -980,17 +1093,20 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val nArg = args[1] as Long - val wrapped: List = try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1002,16 +1118,19 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: java.io.InputStream, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" @@ -1019,15 +1138,15 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt index fb4407e18e8e..af7144386cb3 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -16,7 +16,11 @@ import java.io.InputStream */ class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : PigeonApiInputStream(pigeonRegistrar) { - override fun readBytes(pigeon_instance: InputStream, len: Long, off: Long): InputStreamReadBytesResponse { + override fun readBytes( + pigeon_instance: InputStream, + len: Long, + off: Long + ): InputStreamReadBytesResponse { val bytes = ByteArray(len.toInt()) return InputStreamReadBytesResponse(pigeon_instance.read(bytes, off.toInt(), bytes.size), bytes) } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt index 7c822fe396e6..002a031bf877 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt @@ -6,4 +6,4 @@ package dev.flutter.packages.cross_file_android import org.mockito.kotlin.mock -class TestProxyApiRegistrar : ProxyApiRegistrar(mock(), mock()) \ No newline at end of file +class TestProxyApiRegistrar : ProxyApiRegistrar(mock(), mock()) diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt index f1742acfc98f..94a3db071834 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt @@ -6,10 +6,7 @@ package dev.flutter.packages.cross_file_android.proxies import android.content.ContentResolver import android.net.Uri -import android.os.Looper -import androidx.core.net.toUri import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar -import org.mockito.kotlin.any import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt index a635297ddb6c..e70db89fa606 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -7,13 +7,9 @@ package dev.flutter.packages.cross_file_android.proxies import android.net.Uri import androidx.documentfile.provider.DocumentFile import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar -import org.mockito.Mockito -import org.mockito.Mockito.mockStatic -import org.mockito.kotlin.any -import org.mockito.kotlin.eq import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertTrue +import org.mockito.Mockito.mockStatic import org.mockito.kotlin.mock import org.mockito.kotlin.whenever @@ -26,8 +22,9 @@ class DocumentFileTest { mockStatic(DocumentFile::class.java).use { mockedStatic -> val instance = mock() val singleUri = Uri("myString") - mockedStatic.`when` { DocumentFile.fromSingleUri(registrar.context, singleUri) } - .thenReturn(instance) + mockedStatic + .`when` { DocumentFile.fromSingleUri(registrar.context, singleUri) } + .thenReturn(instance) assertEquals(instance, api.fromSingleUri(singleUri.toString())) } @@ -41,8 +38,9 @@ class DocumentFileTest { mockStatic(DocumentFile::class.java).use { mockedStatic -> val instance = mock() val treeUri = Uri("myString") - mockedStatic.`when` { DocumentFile.fromTreeUri(registrar.context, treeUri) } - .thenReturn(instance) + mockedStatic + .`when` { DocumentFile.fromTreeUri(registrar.context, treeUri) } + .thenReturn(instance) assertEquals(instance, api.fromTreeUri(treeUri.toString())) } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index 17095aa19e4c..bc7530264f43 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -6,17 +6,15 @@ package dev.flutter.packages.cross_file_android.proxies import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar -import org.mockito.ArgumentCaptor -import org.mockito.kotlin.any -import org.mockito.kotlin.capture -import org.mockito.kotlin.eq +import java.io.ByteArrayInputStream import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals +import org.mockito.ArgumentCaptor +import org.mockito.kotlin.capture +import org.mockito.kotlin.eq import org.mockito.kotlin.mock -import org.mockito.kotlin.verify import org.mockito.kotlin.whenever -import java.io.ByteArrayInputStream class InputStreamTest { @Test @@ -30,7 +28,9 @@ class InputStreamTest { val value = 3 whenever(instance.read(bytesCaptor.capture(), eq(off), eq(len))).thenReturn(value) - assertEquals(api.readBytes(instance, len.toLong(), off.toLong()), InputStreamReadBytesResponse(value, bytesCaptor.value)) + assertEquals( + api.readBytes(instance, len.toLong(), off.toLong()), + InputStreamReadBytesResponse(value, bytesCaptor.value)) assertEquals(bytesCaptor.value.size, len) } diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 16295cb199c1..a68fe1f42db7 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -47,7 +47,10 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue,), + appBar: AppBar( + title: const Text('Open a File'), + backgroundColor: Colors.blue, + ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index 2cdee6ecc48e..845f1e365608 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' + show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -20,7 +21,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -29,6 +34,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -40,11 +46,11 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String singleUri})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [DocumentFile.fromTreeUri]. static DocumentFile Function({required String treeUri})? - documentFile_fromTreeUri; + documentFile_fromTreeUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -69,7 +75,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -139,9 +145,10 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; + final Map> + _weakInstances = >{}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -154,7 +161,8 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = + _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -162,11 +170,21 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager, + ); + DocumentFile.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + ContentResolver.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStream.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -183,8 +201,9 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference( + instance, + ); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -245,15 +264,21 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference( + int identifier, + ) { + final PigeonInternalProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance + .pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = + WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -275,7 +300,10 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + void addHostCreatedInstance( + PigeonInternalProxyApiBaseClass instance, + int identifier, + ) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -304,7 +332,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -317,28 +345,35 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', + ); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + assert( + arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', + ); try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); + (instanceManager ?? PigeonInstanceManager.instance).remove( + arg_identifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -353,8 +388,9 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -397,30 +433,30 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference( + readValue(buffer)! as int, + ); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -442,6 +478,7 @@ class _PigeonCodec extends StandardMessageCodec { } } } + /// Representation of a document backed by either a /// android.provider.DocumentsProvider or a raw file on disk. /// @@ -470,8 +507,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String singleUri, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -482,8 +519,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([pigeonVar_instanceIdentifier, singleUri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, singleUri], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -521,8 +559,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String treeUri, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -533,8 +571,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([pigeonVar_instanceIdentifier, treeUri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, treeUri], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -572,39 +611,46 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -623,8 +669,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -656,8 +703,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -689,8 +737,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -723,8 +772,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -756,8 +806,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -789,8 +840,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -822,8 +874,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -856,8 +909,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -889,8 +943,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -953,39 +1008,46 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1009,8 +1071,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1039,8 +1102,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, uri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, uri], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1086,54 +1150,63 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function( - int returnValue, - Uint8List bytes, - )? pigeon_newInstance, + InputStreamReadBytesResponse Function(int returnValue, Uint8List bytes)? + pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', + ); final int? arg_returnValue = (args[1] as int?); - assert(arg_returnValue != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_returnValue != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', + ); final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert(arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); + assert( + arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - returnValue: arg_returnValue!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: arg_returnValue!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1177,39 +1250,46 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1218,10 +1298,7 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// Reads some number of bytes from the input stream and stores them into the /// returns them. - Future readBytes( - int len, - int off, - ) async { + Future readBytes(int len, int off) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -1232,8 +1309,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, len, off]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, len, off], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1265,8 +1343,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1298,8 +1377,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, n]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, n], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1327,4 +1407,3 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } - From d267b0a6f3315dac0a6ebf4b282175428d1a8a34 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 30 Dec 2025 01:33:39 -0500 Subject: [PATCH 052/398] fix file names in android --- ...directory.dart => android_shared_storage_cross_directory.dart} | 0 ...d_storage_file.dart => android_shared_storage_cross_file.dart} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/cross_file/cross_file_android/lib/src/{android_cross_shared_storage_directory.dart => android_shared_storage_cross_directory.dart} (100%) rename packages/cross_file/cross_file_android/lib/src/{android_cross_shared_storage_file.dart => android_shared_storage_cross_file.dart} (100%) diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart similarity index 100% rename from packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_directory.dart rename to packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart similarity index 100% rename from packages/cross_file/cross_file_android/lib/src/android_cross_shared_storage_file.dart rename to packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart From 867331fb85c53b6ae30537c1c95d4b86b8610a1a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 30 Dec 2025 01:36:13 -0500 Subject: [PATCH 053/398] fix file --- .../lib/src/android_shared_storage_cross_directory.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart index d74f3d895413..7fa483efc9ed 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart @@ -4,8 +4,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'android_cross_shared_storage_file.dart'; import 'android_library.g.dart'; +import 'android_shared_storage_cross_file.dart'; /// Implementation of [PlatformSharedStorageXDirectory] for Android. base class AndroidSharedStorageXDirectory From 55f434fe0aac074384d805c5984777ed81c1026d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 30 Dec 2025 01:38:05 -0500 Subject: [PATCH 054/398] fix imports --- .../cross_file_android/lib/src/cross_file_android.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index b8e45bcaf2dd..82389e9fae47 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -5,8 +5,8 @@ import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'android_cross_shared_storage_directory.dart'; -import 'android_cross_shared_storage_file.dart'; +import 'android_shared_storage_cross_directory.dart'; +import 'android_shared_storage_cross_file.dart'; /// Implementation of [CrossFilePlatform] for Android. base class CrossFileAndroid extends CrossFileIO { From 0b0d67409346b1f13144a2ac0871e235bd28a67a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 31 Dec 2025 14:26:54 -0500 Subject: [PATCH 055/398] update order --- .../cross_file/cross_file_android/README.md | 20 +++++++++---------- .../cross_file_android/pubspec.yaml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/cross_file/cross_file_android/README.md b/packages/cross_file/cross_file_android/README.md index f6f307112a6e..68dd5ff78961 100644 --- a/packages/cross_file/cross_file_android/README.md +++ b/packages/cross_file/cross_file_android/README.md @@ -1,15 +1,15 @@ -# cross_file_android +# cross\_file\_android -A new Flutter plugin project. +The Android implementation of [`cross_file`][1]. -## Getting Started +## Usage -This project is a starting point for a Flutter -[plug-in package](https://flutter.dev/to/develop-plugins), -a specialized package that includes platform-specific implementation code for -Android and/or iOS. +This package is [endorsed][2], which means you can simply use `cross_file` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. +[1]: https://pub.dev/packages/cross_file +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 749db2b72f6a..b0a4a17c3f21 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -13,9 +13,9 @@ flutter: implements: cross_file platforms: android: + dartPluginClass: CrossFileAndroid package: dev.flutter.packages.cross_file_android pluginClass: CrossFileAndroidPlugin - dartPluginClass: CrossFileAndroid dependencies: cross_file_io: From 5d7b24c4f9409b675ec2060beca3c01834db9802 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 31 Dec 2025 14:28:46 -0500 Subject: [PATCH 056/398] fix android app pubspec --- .../cross_file_android/example/pubspec.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 06ee82882e02..0b7eb717a13c 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -1,20 +1,24 @@ name: cross_file_android_example description: "Demonstrates how to use the cross_file_android plugin." -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: 'none' environment: sdk: ^3.9.0 flutter: ">=3.35.0" dependencies: + cross_file_android: + # When depending on this package from a real application you should use: + # file_selector_android: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ file_selector: ^1.1.0 flutter: sdk: flutter flutter_driver: sdk: flutter - cross_file_android: - path: ../ - mime: ^2.0.0 video_player: ^2.8.6 dev_dependencies: From bad61df2af87e2def288f2f14f4f6e0e28393a1a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 31 Dec 2025 14:45:52 -0500 Subject: [PATCH 057/398] first android test --- .../android_shared_storage_cross_file.dart | 30 ++- .../cross_file_android/pubspec.yaml | 2 + ...d_shared_storage_cross_directory_test.dart | 0 ...ndroid_shared_storage_cross_file_test.dart | 40 ++++ ..._shared_storage_cross_file_test.mocks.dart | 188 ++++++++++++++++++ 5 files changed, 243 insertions(+), 17 deletions(-) create mode 100644 packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart create mode 100644 packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index 1bfab5193458..89d1483a9c84 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -8,18 +8,18 @@ import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'android_library.g.dart'; +import 'android_library.g.dart' as android; /// Implementation of [PlatformSharedStorageXFile] for Android. base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { /// Constructs an [AndroidSharedStorageXFile]. AndroidSharedStorageXFile(super.params) : super.implementation(); - late final DocumentFile _documentFile = DocumentFile.fromSingleUri( - singleUri: params.uri, - ); + late final android.DocumentFile _documentFile = + android.DocumentFile.fromSingleUri(singleUri: params.uri); - late final ContentResolver _contentResolver = ContentResolver.instance; + late final android.ContentResolver _contentResolver = + android.ContentResolver.instance; @override Future lastModified() async { @@ -36,17 +36,14 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { int bytesToRead = (end ?? await length()) - (start ?? 0); assert(bytesToRead >= 0); - final InputStream? inputStream = await _contentResolver.openInputStream( - params.uri, - ); + final android.InputStream? inputStream = await _contentResolver + .openInputStream(params.uri); const int maxByteArrayLen = 4 * 1024; - if (inputStream case final InputStream inputStream) { - InputStreamReadBytesResponse response = await inputStream.readBytes( - min(bytesToRead, maxByteArrayLen), - start ?? 0, - ); + if (inputStream case final android.InputStream inputStream) { + android.InputStreamReadBytesResponse response = await inputStream + .readBytes(min(bytesToRead, maxByteArrayLen), start ?? 0); bytesToRead -= response.returnValue; while (response.returnValue != -1 && bytesToRead > 0) { @@ -64,10 +61,9 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { @override Future readAsBytes() async { - final InputStream? inputStream = await _contentResolver.openInputStream( - params.uri, - ); - if (inputStream case final InputStream inputStream) { + final android.InputStream? inputStream = await _contentResolver + .openInputStream(params.uri); + if (inputStream case final android.InputStream inputStream) { return inputStream.readAllBytes(); } diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index b0a4a17c3f21..720838a3758d 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -26,8 +26,10 @@ dependencies: sdk: flutter dev_dependencies: + build_runner: ^2.10.4 flutter_test: sdk: flutter + mockito: ^5.4.4 pigeon: ^26.1.4 topics: diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart new file mode 100644 index 000000000000..b2279ff9730b --- /dev/null +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -0,0 +1,40 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_android/src/android_library.g.dart' as android; +import 'package:cross_file_android/src/android_shared_storage_cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'android_shared_storage_cross_file_test.mocks.dart'; + +@GenerateMocks([android.DocumentFile, android.ContentResolver]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + android.PigeonOverrides.pigeon_reset(); + }); + + test('lastModified', () async { + final mockDocumentFile = MockDocumentFile(); + const lastModified = 123; + when(mockDocumentFile.lastModified()).thenAnswer((_) async => lastModified); + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + return mockDocumentFile; + }; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: ''), + ); + + expect( + await file.lastModified(), + DateTime.fromMillisecondsSinceEpoch(lastModified), + ); + }); +} diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart new file mode 100644 index 000000000000..2a5af67fb24a --- /dev/null +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart @@ -0,0 +1,188 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_android/test/android_shared_storage_cross_file_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:cross_file_android/src/android_library.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDocumentFile_1 extends _i1.SmartFake implements _i2.DocumentFile { + _FakeDocumentFile_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeContentResolver_2 extends _i1.SmartFake + implements _i2.ContentResolver { + _FakeContentResolver_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [DocumentFile]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { + MockDocumentFile() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future canRead() => + (super.noSuchMethod( + Invocation.method(#canRead, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future delete() => + (super.noSuchMethod( + Invocation.method(#delete, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future exists() => + (super.noSuchMethod( + Invocation.method(#exists, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future lastModified() => + (super.noSuchMethod( + Invocation.method(#lastModified, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future length() => + (super.noSuchMethod( + Invocation.method(#length, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future isFile() => + (super.noSuchMethod( + Invocation.method(#isFile, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future isDirectory() => + (super.noSuchMethod( + Invocation.method(#isDirectory, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future> listFiles() => + (super.noSuchMethod( + Invocation.method(#listFiles, []), + returnValue: _i3.Future>.value( + <_i2.DocumentFile>[], + ), + ) + as _i3.Future>); + + @override + _i3.Future getUri() => + (super.noSuchMethod( + Invocation.method(#getUri, []), + returnValue: _i3.Future.value( + _i4.dummyValue(this, Invocation.method(#getUri, [])), + ), + ) + as _i3.Future); + + @override + _i2.DocumentFile pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeDocumentFile_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.DocumentFile); +} + +/// A class which mocks [ContentResolver]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { + MockContentResolver() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future<_i2.InputStream?> openInputStream(String? uri) => + (super.noSuchMethod( + Invocation.method(#openInputStream, [uri]), + returnValue: _i3.Future<_i2.InputStream?>.value(), + ) + as _i3.Future<_i2.InputStream?>); + + @override + _i2.ContentResolver pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeContentResolver_2( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.ContentResolver); +} From e7dc9afdfcb9a29a12320f46e03f99f89f496fe6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 5 Jan 2026 14:36:20 -0500 Subject: [PATCH 058/398] first open read test --- .../proxies/AndroidLibrary.g.kt | 654 +++++++----------- .../lib/src/android_library.g.dart | 424 +++++------- .../android_shared_storage_cross_file.dart | 38 +- .../pigeons/android_library.dart | 2 +- ...ndroid_shared_storage_cross_file_test.dart | 118 +++- ..._shared_storage_cross_file_test.mocks.dart | 106 ++- .../test/io_cross_file_test.dart | 2 + 7 files changed, 670 insertions(+), 674 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index 50ac73ccd6c6..3bbdfb43adc7 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// Autogenerated from Pigeon (v26.1.5), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -10,17 +10,16 @@ package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer - private object AndroidLibraryPigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError( - "channel-error", "Unable to establish connection on channel: '$channelName'.", "") - } + return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } fun wrapResult(result: Any?): List { return listOf(result) @@ -28,48 +27,50 @@ private object AndroidLibraryPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf(exception.code, exception.message, exception.details) + listOf( + exception.code, + exception.message, + exception.details + ) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. - * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() /** * Maintains instances used to communicate with the corresponding objects in Dart. * - * Objects stored in this container are represented by an object in Dart that is also stored in an - * InstanceManager with the same identifier. + * Objects stored in this container are represented by an object in Dart that is also stored in + * an InstanceManager with the same identifier. * * When an instance is added with an identifier, either can be used to retrieve the other. * - * Added instances are added as a weak reference and a strong reference. When the strong reference - * is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the - * strong reference is removed and then the identifier is retrieved with the intention to pass the - * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the - * instance is recreated. The strong reference will then need to be removed manually again. + * Added instances are added as a weak reference and a strong reference. When the strong + * reference is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong + * reference is removed and then the identifier is retrieved with the intention to pass the identifier + * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance + * is recreated. The strong reference will then need to be removed manually again. */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class AndroidLibraryPigeonInstanceManager( - private val finalizationListener: PigeonFinalizationListener -) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ +class AndroidLibraryPigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface PigeonFinalizationListener { fun onFinalize(identifier: Long) } @@ -138,20 +139,19 @@ class AndroidLibraryPigeonInstanceManager( private const val tag = "PigeonInstanceManager" /** - * Instantiate a new manager with a listener for garbage collected weak references. + * Instantiate a new manager with a listener for garbage collected weak + * references. * * When the manager is no longer needed, [stopFinalizationListener] must be called. */ - fun create( - finalizationListener: PigeonFinalizationListener - ): AndroidLibraryPigeonInstanceManager { + fun create(finalizationListener: PigeonFinalizationListener): AndroidLibraryPigeonInstanceManager { return AndroidLibraryPigeonInstanceManager(finalizationListener) } } /** - * Removes `identifier` and return its associated strongly referenced instance, if present, from - * the manager. + * Removes `identifier` and return its associated strongly referenced instance, if present, + * from the manager. */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() @@ -161,13 +161,15 @@ class AndroidLibraryPigeonInstanceManager( /** * Retrieves the identifier paired with an instance, if present, otherwise `null`. * + * * If the manager contains a strong reference to `instance`, it will return the identifier * associated with `instance`. If the manager contains only a weak reference to `instance`, a new * strong reference to `instance` will be added and will need to be removed again with [remove]. * + * * If this method returns a nonnull identifier, this method also expects the Dart - * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart - * instance the identifier is associated with. + * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. */ fun getIdentifierForStrongReference(instance: Any?): Long? { logWarningIfFinalizationListenerHasStopped() @@ -184,9 +186,9 @@ class AndroidLibraryPigeonInstanceManager( /** * Adds a new instance that was instantiated from Dart. * - * The same instance can be added multiple times, but each identifier must be unique. This allows - * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are - * equal) to both be added. + * The same instance can be added multiple times, but each identifier must be unique. This + * allows two objects that are equivalent (e.g. the `equals` method returns true and their + * hashcodes are equal) to both be added. * * [identifier] must be >= 0 and unique. */ @@ -198,15 +200,13 @@ class AndroidLibraryPigeonInstanceManager( /** * Adds a new unique instance that was instantiated from the host platform. * - * If the manager contains [instance], this returns the corresponding identifier. If the manager - * does not contain [instance], this adds the instance and returns a unique identifier for that - * [instance]. + * If the manager contains [instance], this returns the corresponding identifier. If the + * manager does not contain [instance], this adds the instance and returns a unique + * identifier for that [instance]. */ fun addHostCreatedInstance(instance: Any): Long { logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { - "Instance of ${instance.javaClass} has already been added." - } + require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } val identifier = nextIdentifier++ addInstance(instance, identifier) return identifier @@ -290,43 +290,39 @@ class AndroidLibraryPigeonInstanceManager( private fun logWarningIfFinalizationListenerHasStopped() { if (hasFinalizationListenerStopped()) { Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped.") + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped." + ) } } } + /** Generated API for managing the Dart and native `InstanceManager`s. */ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { companion object { /** The codec used by AndroidLibraryPigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { AndroidLibraryPigeonCodec() } + val codec: MessageCodec by lazy { + AndroidLibraryPigeonCodec() + } /** * Sets up an instance of `AndroidLibraryPigeonInstanceManagerApi` to handle messages from the * `binaryMessenger`. */ - fun setUpMessageHandlers( - binaryMessenger: BinaryMessenger, - instanceManager: AndroidLibraryPigeonInstanceManager? - ) { + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: AndroidLibraryPigeonInstanceManager?) { run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) if (instanceManager != null) { channel.setMessageHandler { message, reply -> val args = message as List val identifierArg = args[0] as Long - val wrapped: List = - try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -334,20 +330,15 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) if (instanceManager != null) { channel.setMessageHandler { _, reply -> - val wrapped: List = - try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -357,9 +348,9 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { - val channelName = - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) +{ + val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(identifierArg)) { if (it is List<*>) { @@ -370,13 +361,13 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } /** - * Provides implementations for each ProxyApi implementation and provides access to resources needed - * by any implementation. + * Provides implementations for each ProxyApi implementation and provides access to resources + * needed by any implementation. */ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { /** Whether APIs should ignore calling to Dart. */ @@ -393,23 +384,24 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary init { val api = AndroidLibraryPigeonInstanceManagerApi(binaryMessenger) - instanceManager = - AndroidLibraryPigeonInstanceManager.create( - object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier") - } - } - } - }) + instanceManager = AndroidLibraryPigeonInstanceManager.create( + object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier" + ) + } + } + } + } + ) } /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` - * to the Dart `InstanceManager`. + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of + * `DocumentFile` to the Dart `InstanceManager`. */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile @@ -426,8 +418,8 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to - * the Dart `InstanceManager`. + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of + * `InputStream` to the Dart `InstanceManager`. */ abstract fun getPigeonApiInputStream(): PigeonApiInputStream @@ -437,7 +429,6 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } - fun tearDown() { AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) @@ -445,17 +436,17 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } - -private class AndroidLibraryPigeonProxyApiBaseCodec( - val registrar: AndroidLibraryPigeonProxyApiRegistrar -) : AndroidLibraryPigeonCodec() { +private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibraryPigeonProxyApiRegistrar) : AndroidLibraryPigeonCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 128.toByte() -> { val identifier: Long = readValue(buffer) as Long val instance: Any? = registrar.instanceManager.getInstance(identifier) if (instance == null) { - Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") + Log.e( + "PigeonProxyApiBaseCodec", + "Failed to find instance with identifier: $identifier" + ) } return instance } @@ -464,27 +455,16 @@ private class AndroidLibraryPigeonProxyApiBaseCodec( } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || - value is ByteArray || - value is Double || - value is DoubleArray || - value is FloatArray || - value is Int || - value is IntArray || - value is List<*> || - value is Long || - value is LongArray || - value is Map<*, *> || - value is String || - value == null) { + if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { super.writeValue(stream, value) return } fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception") + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception" + ) } if (value is androidx.documentfile.provider.DocumentFile) { @@ -493,19 +473,22 @@ private class AndroidLibraryPigeonProxyApiBaseCodec( logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) } } - } else if (value is android.content.ContentResolver) { + } + else if (value is android.content.ContentResolver) { registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + } + else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) } } - } else if (value is java.io.InputStream) { + } + else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) @@ -518,33 +501,27 @@ private class AndroidLibraryPigeonProxyApiBaseCodec( stream.write(128) writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) } - else -> - throw IllegalArgumentException( - "Unsupported value: '$value' of type '${value.javaClass.name}'") + else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") } } } - private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } /** - * Representation of a document backed by either a android.provider.DocumentsProvider or a raw file - * on disk. + * Representation of a document backed by either a + * android.provider.DocumentsProvider or a raw file on disk. * * See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { +abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { /** Create a DocumentFile representing the single document at the given Uri. */ abstract fun fromSingleUri(singleUri: String): androidx.documentfile.provider.DocumentFile @@ -560,8 +537,8 @@ abstract class PigeonApiDocumentFile( abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean /** - * Returns the time when this file was last modified, measured in milliseconds since January 1st, - * 1970, midnight. + * Returns the time when this file was last modified, measured in + * milliseconds since January 1st, 1970, midnight. */ abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long @@ -574,10 +551,11 @@ abstract class PigeonApiDocumentFile( /** Indicates if this file represents a *directory*. */ abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - /** Returns an list of files contained in the directory represented by this file. */ - abstract fun listFiles( - pigeon_instance: androidx.documentfile.provider.DocumentFile - ): List + /** + * Returns an list of files contained in the directory represented by this + * file. + */ + abstract fun listFiles(pigeon_instance: androidx.documentfile.provider.DocumentFile): List /** A Uri for the underlying document represented by this file. */ abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String @@ -587,24 +565,18 @@ abstract class PigeonApiDocumentFile( fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val singleUriArg = args[1] as String - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.fromSingleUri(singleUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(singleUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -612,24 +584,18 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val treeUriArg = args[1] as String - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.fromTreeUri(treeUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromTreeUri(treeUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -637,21 +603,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -659,19 +620,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -679,19 +637,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -699,21 +654,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -721,19 +671,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -741,19 +688,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.isFile(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.isFile(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -761,21 +705,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.isDirectory(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.isDirectory(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -783,21 +722,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.listFiles(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.listFiles(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -805,19 +739,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.getUri(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.getUri(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -829,19 +760,16 @@ abstract class PigeonApiDocumentFile( @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, - callback: (Result) -> Unit - ) { + fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" @@ -849,17 +777,17 @@ abstract class PigeonApiDocumentFile( channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } /** * This class provides applications access to the content model. @@ -867,40 +795,32 @@ abstract class PigeonApiDocumentFile( * See https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { - /** Helper field for accessing the `ContentResolver` from the current Android `Context`. */ +abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * Helper field for accessing the `ContentResolver` from the current Android + * `Context`. + */ abstract fun instance(): android.content.ContentResolver /** Open a stream on to the content associated with a content URI. */ - abstract fun openInputStream( - pigeon_instance: android.content.ContentResolver, - uri: String - ): java.io.InputStream? + abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -908,22 +828,17 @@ abstract class PigeonApiContentResolver( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as android.content.ContentResolver val uriArg = args[1] as String - val wrapped: List = - try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -935,19 +850,16 @@ abstract class PigeonApiContentResolver( @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: android.content.ContentResolver, - callback: (Result) -> Unit - ) { + fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" @@ -955,86 +867,71 @@ abstract class PigeonApiContentResolver( channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } /** Return type for [InputStream.readBytes] that handles returning two values. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { - abstract fun returnValue( - pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - ): Long +abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long - abstract fun bytes( - pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - ): ByteArray + abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray @Suppress("LocalVariableName", "FunctionName") - /** - * Creates a Dart instance of InputStreamReadBytesResponse and attaches it to - * [pigeon_instanceArg]. - */ - fun pigeon_newInstance( - pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, - callback: (Result) -> Unit - ) { + /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val returnValueArg = returnValue(pigeon_instanceArg) val bytesArg = bytes(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec - val channelName = - "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } /** - * This abstract class is the superclass of all classes representing an input stream of bytes. + * This abstract class is the superclass of all classes representing an input + * stream of bytes. * * See https://developer.android.com/reference/java/io/InputStream. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStream( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { - /** Reads some number of bytes from the input stream and stores them into the returns them. */ - abstract fun readBytes( - pigeon_instance: java.io.InputStream, - len: Long, - off: Long - ): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * Reads some number of bytes from the input stream and stores them into the + * returns them. + */ + abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse /** Reads all remaining bytes from the input stream. */ abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray @@ -1047,23 +944,17 @@ abstract class PigeonApiInputStream( fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val lenArg = args[1] as Long - val offArg = args[2] as Long - val wrapped: List = - try { - listOf(api.readBytes(pigeon_instanceArg, lenArg, offArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.readBytes(pigeon_instanceArg, lenArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1071,21 +962,16 @@ abstract class PigeonApiInputStream( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = - try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1093,20 +979,17 @@ abstract class PigeonApiInputStream( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val nArg = args[1] as Long - val wrapped: List = - try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1118,19 +1001,16 @@ abstract class PigeonApiInputStream( @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: java.io.InputStream, - callback: (Result) -> Unit - ) { + fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" @@ -1138,15 +1018,15 @@ abstract class PigeonApiInputStream( channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index 845f1e365608..b7224991b47c 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.4), do not edit directly. +// Autogenerated from Pigeon (v26.1.5), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -9,8 +9,7 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' - show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -21,11 +20,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -34,7 +29,6 @@ List wrapResponse({ } return [error.code, error.message, error.details]; } - /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -46,11 +40,11 @@ List wrapResponse({ class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String singleUri})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [DocumentFile.fromTreeUri]. static DocumentFile Function({required String treeUri})? - documentFile_fromTreeUri; + documentFile_fromTreeUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -75,7 +69,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -145,10 +139,9 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> - _weakInstances = >{}; - final Map _strongInstances = - {}; + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -161,8 +154,7 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = - _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -170,21 +162,11 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers( - instanceManager: instanceManager, - ); - DocumentFile.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - ContentResolver.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStream.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -201,9 +183,8 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference( - instance, - ); + _weakInstances[identifier] = + WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -264,21 +245,15 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference( - int identifier, - ) { - final PigeonInternalProxyApiBaseClass? weakInstance = - _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = - _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance - .pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = - WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -300,10 +275,7 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance( - PigeonInternalProxyApiBaseClass instance, - int identifier, - ) { + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -332,7 +304,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -345,35 +317,28 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert( - arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', - ); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); try { - (instanceManager ?? PigeonInstanceManager.instance).remove( - arg_identifier!, - ); + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -388,9 +353,8 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -433,31 +397,31 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference( - readValue(buffer)! as int, - ); - default: - return super.readValueOfType(type, buffer); - } - } + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } } + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -478,7 +442,6 @@ class _PigeonCodec extends StandardMessageCodec { } } } - /// Representation of a document backed by either a /// android.provider.DocumentsProvider or a raw file on disk. /// @@ -507,8 +470,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String singleUri, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -519,9 +482,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, singleUri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([pigeonVar_instanceIdentifier, singleUri]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -559,8 +521,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String treeUri, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -571,9 +533,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, treeUri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([pigeonVar_instanceIdentifier, treeUri]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -611,46 +572,39 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -669,9 +623,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -703,9 +656,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -737,9 +689,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -772,9 +723,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -806,9 +756,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -840,9 +789,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -874,9 +822,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -909,9 +856,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -943,9 +889,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1008,46 +953,39 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1071,9 +1009,8 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1102,9 +1039,8 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, uri], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, uri]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1150,63 +1086,54 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function(int returnValue, Uint8List bytes)? - pigeon_newInstance, + InputStreamReadBytesResponse Function( + int returnValue, + Uint8List bytes, + )? pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); final int? arg_returnValue = (args[1] as int?); - assert( - arg_returnValue != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_returnValue != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert( - arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.', - ); + assert(arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - returnValue: arg_returnValue!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: arg_returnValue!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1250,46 +1177,39 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1298,7 +1218,7 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// Reads some number of bytes from the input stream and stores them into the /// returns them. - Future readBytes(int len, int off) async { + Future readBytes(int len) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -1309,9 +1229,8 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, len, off], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, len]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1343,9 +1262,8 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1377,9 +1295,8 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, n], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, n]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1407,3 +1324,4 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } + diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index 89d1483a9c84..ea9a9c7cc5c0 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -4,9 +4,9 @@ import 'dart:convert'; import 'dart:math'; -import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; import 'android_library.g.dart' as android; @@ -21,6 +21,10 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { late final android.ContentResolver _contentResolver = android.ContentResolver.instance; + /// Maximum number of bytes to read at a time. + @visibleForTesting + static const int maxByteArrayLen = 4 * 1024; + @override Future lastModified() async { return DateTime.fromMillisecondsSinceEpoch( @@ -39,23 +43,24 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { final android.InputStream? inputStream = await _contentResolver .openInputStream(params.uri); - const int maxByteArrayLen = 4 * 1024; - if (inputStream case final android.InputStream inputStream) { + if (start != null && start > 0) { + await inputStream.skip(start); + } + android.InputStreamReadBytesResponse response = await inputStream - .readBytes(min(bytesToRead, maxByteArrayLen), start ?? 0); + .readBytes(min(bytesToRead, maxByteArrayLen)); bytesToRead -= response.returnValue; - while (response.returnValue != -1 && bytesToRead > 0) { + do { yield response.bytes; response = await inputStream.readBytes( min(bytesToRead, maxByteArrayLen), - 0, ); bytesToRead -= response.returnValue; - } + } while(response.returnValue != -1 && bytesToRead > 0); } else { - throw _createNullInputStreamError(); + throw NullInputStreamError(params.uri); } } @@ -67,7 +72,7 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { return inputStream.readAllBytes(); } - throw _createNullInputStreamError(); + throw NullInputStreamError(params.uri); } @override @@ -82,11 +87,14 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { Future exists() async { return await _documentFile.exists() && await _documentFile.isFile(); } +} - UnsupportedError _createNullInputStreamError() { - return UnsupportedError( - 'Failed to get native InputStream from file with path: ${params.uri}. ' - 'App may not have permissions to access file.', - ); - } +/// Error thrown when the native [android.InputStream] is not accessible. +class NullInputStreamError extends UnsupportedError { + /// Constructs a [NullInputStreamError]. + NullInputStreamError(String uri) + : super( + 'Failed to get native InputStream from file with path: $uri. ' + 'App may not have permissions to access file.', + ); } diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index 77ff97184812..3c1181c5429a 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -103,7 +103,7 @@ abstract class InputStreamReadBytesResponse { abstract class InputStream { /// Reads some number of bytes from the input stream and stores them into the /// returns them. - InputStreamReadBytesResponse readBytes(int len, int off); + InputStreamReadBytesResponse readBytes(int len); /// Reads all remaining bytes from the input stream. Uint8List readAllBytes(); diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart index b2279ff9730b..212b95eaa010 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:typed_data'; + import 'package:cross_file_android/src/android_library.g.dart' as android; import 'package:cross_file_android/src/android_shared_storage_cross_file.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -11,7 +13,28 @@ import 'package:mockito/mockito.dart'; import 'android_shared_storage_cross_file_test.mocks.dart'; -@GenerateMocks([android.DocumentFile, android.ContentResolver]) +// Test byte array that decodes to 'Hello, World!' in UTF-8. +final testBytes = Uint8List.fromList([ + 72, + 101, + 108, + 108, + 111, + 44, + 32, + 87, + 111, + 114, + 108, + 100, + 33, +]); + +@GenerateMocks([ + android.ContentResolver, + android.DocumentFile, + android.InputStream, +]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -23,13 +46,16 @@ void main() { final mockDocumentFile = MockDocumentFile(); const lastModified = 123; when(mockDocumentFile.lastModified()).thenAnswer((_) async => lastModified); + + const uri = 'uri'; android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); return mockDocumentFile; }; final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: ''), + const PlatformSharedStorageXFileCreationParams(uri: uri), ); expect( @@ -37,4 +63,92 @@ void main() { DateTime.fromMillisecondsSinceEpoch(lastModified), ); }); + + test('length', () async { + final mockDocumentFile = MockDocumentFile(); + const length = 123; + when(mockDocumentFile.length()).thenAnswer((_) async => length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(await file.length(), length); + }); + + group('openRead', () { + void setUpInputStreamWithBytes( + MockInputStream mockInputStream, + Uint8List bytes, + ) { + Iterable remainingBytes = bytes.toList(); + + when(mockInputStream.skip(any)).thenAnswer((Invocation invocation) async { + final amount = invocation.positionalArguments[0] as int; + if (amount < 0) { + return 0; + } + + final Iterable newRemainingBytes = remainingBytes.skip(amount); + + final int diff = remainingBytes.length - newRemainingBytes.length; + remainingBytes = newRemainingBytes; + return diff; + }); + + when(mockInputStream.readBytes(any)).thenAnswer(( + Invocation invocation, + ) async { + final len = invocation.positionalArguments[0] as int; + + final List bytesRead = remainingBytes.take(len).toList(); + remainingBytes = remainingBytes.skip(len); + + return android.InputStreamReadBytesResponse.pigeon_detached( + returnValue: remainingBytes.isEmpty ? -1 : bytesRead.length, + bytes: Uint8List.fromList(bytesRead), + ); + }); + } + + Uint8List combineLists(List lists) { + return Uint8List.fromList( + lists.expand((Uint8List element) => element).toList(), + ); + } + + test('openRead', () async { + final mockDocumentFile = MockDocumentFile(); + when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final mockInputStream = MockInputStream(); + setUpInputStreamWithBytes(mockInputStream, testBytes); + + final mockContentResolver = MockContentResolver(); + when( + mockContentResolver.openInputStream(uri), + ).thenAnswer((_) async => mockInputStream); + android.PigeonOverrides.contentResolver_instance = mockContentResolver; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(combineLists(await file.openRead().toList()), testBytes); + }); + }); } diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart index 2a5af67fb24a..e9d0eefc32f2 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart @@ -4,6 +4,7 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; +import 'dart:typed_data' as _i5; import 'package:cross_file_android/src/android_library.g.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; @@ -30,17 +31,69 @@ class _FakePigeonInstanceManager_0 extends _i1.SmartFake : super(parent, parentInvocation); } -class _FakeDocumentFile_1 extends _i1.SmartFake implements _i2.DocumentFile { - _FakeDocumentFile_1(Object parent, Invocation parentInvocation) +class _FakeContentResolver_1 extends _i1.SmartFake + implements _i2.ContentResolver { + _FakeContentResolver_1(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeContentResolver_2 extends _i1.SmartFake - implements _i2.ContentResolver { - _FakeContentResolver_2(Object parent, Invocation parentInvocation) +class _FakeDocumentFile_2 extends _i1.SmartFake implements _i2.DocumentFile { + _FakeDocumentFile_2(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } +class _FakeInputStreamReadBytesResponse_3 extends _i1.SmartFake + implements _i2.InputStreamReadBytesResponse { + _FakeInputStreamReadBytesResponse_3( + Object parent, + Invocation parentInvocation, + ) : super(parent, parentInvocation); +} + +class _FakeInputStream_4 extends _i1.SmartFake implements _i2.InputStream { + _FakeInputStream_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [ContentResolver]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { + MockContentResolver() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future<_i2.InputStream?> openInputStream(String? uri) => + (super.noSuchMethod( + Invocation.method(#openInputStream, [uri]), + returnValue: _i3.Future<_i2.InputStream?>.value(), + ) + as _i3.Future<_i2.InputStream?>); + + @override + _i2.ContentResolver pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeContentResolver_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.ContentResolver); +} + /// A class which mocks [DocumentFile]. /// /// See the documentation for Mockito's code generation for more information. @@ -140,7 +193,7 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { _i2.DocumentFile pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeDocumentFile_1( + returnValue: _FakeDocumentFile_2( this, Invocation.method(#pigeon_copy, []), ), @@ -148,11 +201,11 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { as _i2.DocumentFile); } -/// A class which mocks [ContentResolver]. +/// A class which mocks [InputStream]. /// /// See the documentation for Mockito's code generation for more information. -class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { - MockContentResolver() { +class MockInputStream extends _i1.Mock implements _i2.InputStream { + MockInputStream() { _i1.throwOnMissingStub(this); } @@ -168,21 +221,42 @@ class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { as _i2.PigeonInstanceManager); @override - _i3.Future<_i2.InputStream?> openInputStream(String? uri) => + _i3.Future<_i2.InputStreamReadBytesResponse> readBytes(int? len) => (super.noSuchMethod( - Invocation.method(#openInputStream, [uri]), - returnValue: _i3.Future<_i2.InputStream?>.value(), + Invocation.method(#readBytes, [len]), + returnValue: _i3.Future<_i2.InputStreamReadBytesResponse>.value( + _FakeInputStreamReadBytesResponse_3( + this, + Invocation.method(#readBytes, [len]), + ), + ), ) - as _i3.Future<_i2.InputStream?>); + as _i3.Future<_i2.InputStreamReadBytesResponse>); @override - _i2.ContentResolver pigeon_copy() => + _i3.Future<_i5.Uint8List> readAllBytes() => + (super.noSuchMethod( + Invocation.method(#readAllBytes, []), + returnValue: _i3.Future<_i5.Uint8List>.value(_i5.Uint8List(0)), + ) + as _i3.Future<_i5.Uint8List>); + + @override + _i3.Future skip(int? n) => + (super.noSuchMethod( + Invocation.method(#skip, [n]), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i2.InputStream pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeContentResolver_2( + returnValue: _FakeInputStream_4( this, Invocation.method(#pigeon_copy, []), ), ) - as _i2.ContentResolver); + as _i2.InputStream); } diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index d30aaf92c0a4..4048de649d12 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -51,6 +51,8 @@ void main() { PlatformXFileCreationParams(uri: testFile.path), ); + print(await file.readAsBytes()); + expect(await file.readAsBytes(), await testFile.readAsBytes()); }); From b1a1de6a66f62c8df64280c21c91b385b835870b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 5 Jan 2026 14:59:49 -0500 Subject: [PATCH 059/398] formatting and 2 tests --- .../proxies/AndroidLibrary.g.kt | 650 +++++++++++------- .../lib/src/android_library.g.dart | 420 ++++++----- .../android_shared_storage_cross_file.dart | 16 +- ...d_shared_storage_cross_directory_test.dart | 1 + ...ndroid_shared_storage_cross_file_test.dart | 57 +- 5 files changed, 686 insertions(+), 458 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index 3bbdfb43adc7..0bac60be85c1 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -10,16 +10,17 @@ package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object AndroidLibraryPigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + return FlutterError( + "channel-error", "Unable to establish connection on channel: '$channelName'.", "") + } fun wrapResult(result: Any?): List { return listOf(result) @@ -27,50 +28,48 @@ private object AndroidLibraryPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() /** * Maintains instances used to communicate with the corresponding objects in Dart. * - * Objects stored in this container are represented by an object in Dart that is also stored in - * an InstanceManager with the same identifier. + * Objects stored in this container are represented by an object in Dart that is also stored in an + * InstanceManager with the same identifier. * * When an instance is added with an identifier, either can be used to retrieve the other. * - * Added instances are added as a weak reference and a strong reference. When the strong - * reference is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong - * reference is removed and then the identifier is retrieved with the intention to pass the identifier - * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance - * is recreated. The strong reference will then need to be removed manually again. + * Added instances are added as a weak reference and a strong reference. When the strong reference + * is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the + * strong reference is removed and then the identifier is retrieved with the intention to pass the + * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the + * instance is recreated. The strong reference will then need to be removed manually again. */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class AndroidLibraryPigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ +class AndroidLibraryPigeonInstanceManager( + private val finalizationListener: PigeonFinalizationListener +) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface PigeonFinalizationListener { fun onFinalize(identifier: Long) } @@ -139,19 +138,20 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige private const val tag = "PigeonInstanceManager" /** - * Instantiate a new manager with a listener for garbage collected weak - * references. + * Instantiate a new manager with a listener for garbage collected weak references. * * When the manager is no longer needed, [stopFinalizationListener] must be called. */ - fun create(finalizationListener: PigeonFinalizationListener): AndroidLibraryPigeonInstanceManager { + fun create( + finalizationListener: PigeonFinalizationListener + ): AndroidLibraryPigeonInstanceManager { return AndroidLibraryPigeonInstanceManager(finalizationListener) } } /** - * Removes `identifier` and return its associated strongly referenced instance, if present, - * from the manager. + * Removes `identifier` and return its associated strongly referenced instance, if present, from + * the manager. */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() @@ -161,15 +161,13 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Retrieves the identifier paired with an instance, if present, otherwise `null`. * - * * If the manager contains a strong reference to `instance`, it will return the identifier * associated with `instance`. If the manager contains only a weak reference to `instance`, a new * strong reference to `instance` will be added and will need to be removed again with [remove]. * - * * If this method returns a nonnull identifier, this method also expects the Dart - * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - * identifier is associated with. + * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart + * instance the identifier is associated with. */ fun getIdentifierForStrongReference(instance: Any?): Long? { logWarningIfFinalizationListenerHasStopped() @@ -186,9 +184,9 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Adds a new instance that was instantiated from Dart. * - * The same instance can be added multiple times, but each identifier must be unique. This - * allows two objects that are equivalent (e.g. the `equals` method returns true and their - * hashcodes are equal) to both be added. + * The same instance can be added multiple times, but each identifier must be unique. This allows + * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are + * equal) to both be added. * * [identifier] must be >= 0 and unique. */ @@ -200,13 +198,15 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Adds a new unique instance that was instantiated from the host platform. * - * If the manager contains [instance], this returns the corresponding identifier. If the - * manager does not contain [instance], this adds the instance and returns a unique - * identifier for that [instance]. + * If the manager contains [instance], this returns the corresponding identifier. If the manager + * does not contain [instance], this adds the instance and returns a unique identifier for that + * [instance]. */ fun addHostCreatedInstance(instance: Any): Long { logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } + require(!containsInstance(instance)) { + "Instance of ${instance.javaClass} has already been added." + } val identifier = nextIdentifier++ addInstance(instance, identifier) return identifier @@ -290,39 +290,43 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige private fun logWarningIfFinalizationListenerHasStopped() { if (hasFinalizationListenerStopped()) { Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped." - ) + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped.") } } } - /** Generated API for managing the Dart and native `InstanceManager`s. */ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { companion object { /** The codec used by AndroidLibraryPigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { - AndroidLibraryPigeonCodec() - } + val codec: MessageCodec by lazy { AndroidLibraryPigeonCodec() } /** * Sets up an instance of `AndroidLibraryPigeonInstanceManagerApi` to handle messages from the * `binaryMessenger`. */ - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: AndroidLibraryPigeonInstanceManager?) { + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + instanceManager: AndroidLibraryPigeonInstanceManager? + ) { run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", + codec) if (instanceManager != null) { channel.setMessageHandler { message, reply -> val args = message as List val identifierArg = args[0] as Long - val wrapped: List = try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -330,15 +334,20 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", + codec) if (instanceManager != null) { channel.setMessageHandler { _, reply -> - val wrapped: List = try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -348,9 +357,9 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) -{ - val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(identifierArg)) { if (it is List<*>) { @@ -361,13 +370,13 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } /** - * Provides implementations for each ProxyApi implementation and provides access to resources - * needed by any implementation. + * Provides implementations for each ProxyApi implementation and provides access to resources needed + * by any implementation. */ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { /** Whether APIs should ignore calling to Dart. */ @@ -384,24 +393,23 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary init { val api = AndroidLibraryPigeonInstanceManagerApi(binaryMessenger) - instanceManager = AndroidLibraryPigeonInstanceManager.create( - object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier" - ) - } - } - } - } - ) + instanceManager = + AndroidLibraryPigeonInstanceManager.create( + object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier") + } + } + } + }) } /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of - * `DocumentFile` to the Dart `InstanceManager`. + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` + * to the Dart `InstanceManager`. */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile @@ -418,8 +426,8 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of - * `InputStream` to the Dart `InstanceManager`. + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to + * the Dart `InstanceManager`. */ abstract fun getPigeonApiInputStream(): PigeonApiInputStream @@ -429,6 +437,7 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } + fun tearDown() { AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) @@ -436,17 +445,17 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } -private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibraryPigeonProxyApiRegistrar) : AndroidLibraryPigeonCodec() { + +private class AndroidLibraryPigeonProxyApiBaseCodec( + val registrar: AndroidLibraryPigeonProxyApiRegistrar +) : AndroidLibraryPigeonCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 128.toByte() -> { val identifier: Long = readValue(buffer) as Long val instance: Any? = registrar.instanceManager.getInstance(identifier) if (instance == null) { - Log.e( - "PigeonProxyApiBaseCodec", - "Failed to find instance with identifier: $identifier" - ) + Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") } return instance } @@ -455,16 +464,27 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { + if (value is Boolean || + value is ByteArray || + value is Double || + value is DoubleArray || + value is FloatArray || + value is Int || + value is IntArray || + value is List<*> || + value is Long || + value is LongArray || + value is Map<*, *> || + value is String || + value == null) { super.writeValue(stream, value) return } fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception" - ) + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception") } if (value is androidx.documentfile.provider.DocumentFile) { @@ -473,22 +493,19 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) } } - } - else if (value is android.content.ContentResolver) { + } else if (value is android.content.ContentResolver) { registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } - else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + } else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) } } - } - else if (value is java.io.InputStream) { + } else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) @@ -501,27 +518,33 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar stream.write(128) writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) } - else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") + else -> + throw IllegalArgumentException( + "Unsupported value: '$value' of type '${value.javaClass.name}'") } } } + private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } /** - * Representation of a document backed by either a - * android.provider.DocumentsProvider or a raw file on disk. + * Representation of a document backed by either a android.provider.DocumentsProvider or a raw file + * on disk. * * See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { +abstract class PigeonApiDocumentFile( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { /** Create a DocumentFile representing the single document at the given Uri. */ abstract fun fromSingleUri(singleUri: String): androidx.documentfile.provider.DocumentFile @@ -537,8 +560,8 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean /** - * Returns the time when this file was last modified, measured in - * milliseconds since January 1st, 1970, midnight. + * Returns the time when this file was last modified, measured in milliseconds since January 1st, + * 1970, midnight. */ abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long @@ -551,11 +574,10 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig /** Indicates if this file represents a *directory*. */ abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - /** - * Returns an list of files contained in the directory represented by this - * file. - */ - abstract fun listFiles(pigeon_instance: androidx.documentfile.provider.DocumentFile): List + /** Returns an list of files contained in the directory represented by this file. */ + abstract fun listFiles( + pigeon_instance: androidx.documentfile.provider.DocumentFile + ): List /** A Uri for the underlying document represented by this file. */ abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String @@ -565,18 +587,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val singleUriArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(singleUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromSingleUri(singleUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -584,18 +612,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val treeUriArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromTreeUri(treeUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromTreeUri(treeUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -603,16 +637,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -620,16 +659,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -637,16 +679,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -654,16 +699,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -671,16 +721,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -688,16 +741,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.isFile(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.isFile(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -705,16 +761,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.isDirectory(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.isDirectory(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -722,16 +783,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.listFiles(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.listFiles(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -739,16 +805,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.getUri(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getUri(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -760,16 +829,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" @@ -777,17 +849,17 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** * This class provides applications access to the content model. @@ -795,32 +867,40 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig * See https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * Helper field for accessing the `ContentResolver` from the current Android - * `Context`. - */ +abstract class PigeonApiContentResolver( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + /** Helper field for accessing the `ContentResolver` from the current Android `Context`. */ abstract fun instance(): android.content.ContentResolver /** Open a stream on to the content associated with a content URI. */ - abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? + abstract fun openInputStream( + pigeon_instance: android.content.ContentResolver, + uri: String + ): java.io.InputStream? companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -828,17 +908,22 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as android.content.ContentResolver val uriArg = args[1] as String - val wrapped: List = try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -850,16 +935,19 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: android.content.ContentResolver, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" @@ -867,71 +955,85 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** Return type for [InputStream.readBytes] that handles returning two values. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - abstract fun returnValue(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long +abstract class PigeonApiInputStreamReadBytesResponse( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + abstract fun returnValue( + pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + ): Long - abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray + abstract fun bytes( + pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse + ): ByteArray @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) -{ + /** + * Creates a Dart instance of InputStreamReadBytesResponse and attaches it to + * [pigeon_instanceArg]. + */ + fun pigeon_newInstance( + pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val returnValueArg = returnValue(pigeon_instanceArg) val bytesArg = bytes(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channelName = + "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** - * This abstract class is the superclass of all classes representing an input - * stream of bytes. + * This abstract class is the superclass of all classes representing an input stream of bytes. * * See https://developer.android.com/reference/java/io/InputStream. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * Reads some number of bytes from the input stream and stores them into the - * returns them. - */ - abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +abstract class PigeonApiInputStream( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + /** Reads some number of bytes from the input stream and stores them into the returns them. */ + abstract fun readBytes( + pigeon_instance: java.io.InputStream, + len: Long + ): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse /** Reads all remaining bytes from the input stream. */ abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray @@ -944,17 +1046,22 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val lenArg = args[1] as Long - val wrapped: List = try { - listOf(api.readBytes(pigeon_instanceArg, lenArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readBytes(pigeon_instanceArg, lenArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -962,16 +1069,21 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -979,17 +1091,20 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val nArg = args[1] as Long - val wrapped: List = try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1001,16 +1116,19 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: java.io.InputStream, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" @@ -1018,15 +1136,15 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index b7224991b47c..75963c015fb0 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' + show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -20,7 +21,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -29,6 +34,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -40,11 +46,11 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String singleUri})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [DocumentFile.fromTreeUri]. static DocumentFile Function({required String treeUri})? - documentFile_fromTreeUri; + documentFile_fromTreeUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -69,7 +75,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -139,9 +145,10 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; + final Map> + _weakInstances = >{}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -154,7 +161,8 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = + _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -162,11 +170,21 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager, + ); + DocumentFile.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + ContentResolver.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStream.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -183,8 +201,9 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference( + instance, + ); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -245,15 +264,21 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference( + int identifier, + ) { + final PigeonInternalProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance + .pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = + WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -275,7 +300,10 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + void addHostCreatedInstance( + PigeonInternalProxyApiBaseClass instance, + int identifier, + ) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -304,7 +332,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -317,28 +345,35 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', + ); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + assert( + arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', + ); try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); + (instanceManager ?? PigeonInstanceManager.instance).remove( + arg_identifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -353,8 +388,9 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -397,30 +433,30 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference( + readValue(buffer)! as int, + ); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -442,6 +478,7 @@ class _PigeonCodec extends StandardMessageCodec { } } } + /// Representation of a document backed by either a /// android.provider.DocumentsProvider or a raw file on disk. /// @@ -470,8 +507,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String singleUri, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -482,8 +519,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([pigeonVar_instanceIdentifier, singleUri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, singleUri], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -521,8 +559,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String treeUri, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -533,8 +571,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([pigeonVar_instanceIdentifier, treeUri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, treeUri], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -572,39 +611,46 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -623,8 +669,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -656,8 +703,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -689,8 +737,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -723,8 +772,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -756,8 +806,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -789,8 +840,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -822,8 +874,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -856,8 +909,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -889,8 +943,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -953,39 +1008,46 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1009,8 +1071,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1039,8 +1102,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, uri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, uri], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1086,54 +1150,63 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function( - int returnValue, - Uint8List bytes, - )? pigeon_newInstance, + InputStreamReadBytesResponse Function(int returnValue, Uint8List bytes)? + pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', + ); final int? arg_returnValue = (args[1] as int?); - assert(arg_returnValue != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_returnValue != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', + ); final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert(arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); + assert( + arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - returnValue: arg_returnValue!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + returnValue: arg_returnValue!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1177,39 +1250,46 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1229,8 +1309,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, len]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, len], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1262,8 +1343,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1295,8 +1377,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, n]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, n], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1324,4 +1407,3 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } - diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index ea9a9c7cc5c0..319b61fbad43 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -21,9 +21,12 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { late final android.ContentResolver _contentResolver = android.ContentResolver.instance; - /// Maximum number of bytes to read at a time. + /// Maximum number of bytes to read at a time from the native Android + /// InputStream. + /// + /// Only visible for testing. @visibleForTesting - static const int maxByteArrayLen = 4 * 1024; + static const int maxByteArrayLen = 5; //4 * 1024; @override Future lastModified() async { @@ -51,14 +54,17 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { android.InputStreamReadBytesResponse response = await inputStream .readBytes(min(bytesToRead, maxByteArrayLen)); bytesToRead -= response.returnValue; + yield response.bytes; - do { - yield response.bytes; + var returnValue = -1; + while (returnValue != -1 && bytesToRead > 0) { response = await inputStream.readBytes( min(bytesToRead, maxByteArrayLen), ); + yield response.bytes; + returnValue = response.returnValue; bytesToRead -= response.returnValue; - } while(response.returnValue != -1 && bytesToRead > 0); + } } else { throw NullInputStreamError(params.uri); } diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart index e69de29bb2d1..8b137891791f 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart @@ -0,0 +1 @@ + diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart index 212b95eaa010..bbac20313f89 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -13,23 +13,6 @@ import 'package:mockito/mockito.dart'; import 'android_shared_storage_cross_file_test.mocks.dart'; -// Test byte array that decodes to 'Hello, World!' in UTF-8. -final testBytes = Uint8List.fromList([ - 72, - 101, - 108, - 108, - 111, - 44, - 32, - 87, - 111, - 114, - 108, - 100, - 33, -]); - @GenerateMocks([ android.ContentResolver, android.DocumentFile, @@ -124,7 +107,9 @@ void main() { ); } - test('openRead', () async { + test('openRead finishes successfully', () async { + final testBytes = Uint8List.fromList([72, 101, 108]); + final mockDocumentFile = MockDocumentFile(); when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); @@ -150,5 +135,41 @@ void main() { expect(combineLists(await file.openRead().toList()), testBytes); }); + + test( + 'openRead finishes successfully with file larger than max array len', + () async { + final testBytes = Uint8List.fromList( + List.filled(AndroidSharedStorageXFile.maxByteArrayLen + 1, 0), + ); + + final mockDocumentFile = MockDocumentFile(); + when( + mockDocumentFile.length(), + ).thenAnswer((_) async => testBytes.length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final mockInputStream = MockInputStream(); + setUpInputStreamWithBytes(mockInputStream, testBytes); + + final mockContentResolver = MockContentResolver(); + when( + mockContentResolver.openInputStream(uri), + ).thenAnswer((_) async => mockInputStream); + android.PigeonOverrides.contentResolver_instance = mockContentResolver; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(combineLists(await file.openRead().toList()), testBytes); + }, + ); }); } From 9d3e51fb24c1ec398b528b9c43ce41a6e54e5d0d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:03:45 -0500 Subject: [PATCH 060/398] add array subset test --- .../proxies/InputStreamProxyApi.kt | 3 +- .../android_shared_storage_cross_file.dart | 14 +++------ ...ndroid_shared_storage_cross_file_test.dart | 31 ++++++++++++++++++- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt index af7144386cb3..a0a90efab0be 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -19,10 +19,9 @@ class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : override fun readBytes( pigeon_instance: InputStream, len: Long, - off: Long ): InputStreamReadBytesResponse { val bytes = ByteArray(len.toInt()) - return InputStreamReadBytesResponse(pigeon_instance.read(bytes, off.toInt(), bytes.size), bytes) + return InputStreamReadBytesResponse(pigeon_instance.read(bytes), bytes) } override fun readAllBytes(pigeon_instance: InputStream): ByteArray { diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index 319b61fbad43..8481c29e8350 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -26,7 +26,7 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { /// /// Only visible for testing. @visibleForTesting - static const int maxByteArrayLen = 5; //4 * 1024; + static const int maxByteArrayLen = 4 * 1024; @override Future lastModified() async { @@ -51,20 +51,14 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { await inputStream.skip(start); } - android.InputStreamReadBytesResponse response = await inputStream - .readBytes(min(bytesToRead, maxByteArrayLen)); - bytesToRead -= response.returnValue; - yield response.bytes; - - var returnValue = -1; - while (returnValue != -1 && bytesToRead > 0) { + late android.InputStreamReadBytesResponse response; + do { response = await inputStream.readBytes( min(bytesToRead, maxByteArrayLen), ); yield response.bytes; - returnValue = response.returnValue; bytesToRead -= response.returnValue; - } + } while (response.returnValue > -1 && bytesToRead > 0); } else { throw NullInputStreamError(params.uri); } diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart index bbac20313f89..4f07d0732eab 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -108,7 +108,7 @@ void main() { } test('openRead finishes successfully', () async { - final testBytes = Uint8List.fromList([72, 101, 108]); + final testBytes = Uint8List.fromList([0, 1, 2]); final mockDocumentFile = MockDocumentFile(); when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); @@ -171,5 +171,34 @@ void main() { expect(combineLists(await file.openRead().toList()), testBytes); }, ); + + test('openRead finishes successfully with subset of array', () async { + final testBytes = Uint8List.fromList([0, 0, 0, 1, 1, 1, 0, 0, 0]); + + final mockDocumentFile = MockDocumentFile(); + when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final mockInputStream = MockInputStream(); + setUpInputStreamWithBytes(mockInputStream, testBytes); + + final mockContentResolver = MockContentResolver(); + when( + mockContentResolver.openInputStream(uri), + ).thenAnswer((_) async => mockInputStream); + android.PigeonOverrides.contentResolver_instance = mockContentResolver; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(combineLists(await file.openRead(3, 6).toList()), [1, 1, 1]); + }); }); } From b39f7fb765c60a8e79a28a65cc79292279bf91e0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 5 Jan 2026 18:24:20 -0500 Subject: [PATCH 061/398] fix android test and finish file tests --- .../proxies/InputStreamTest.kt | 5 +- ...ndroid_shared_storage_cross_file_test.dart | 99 +++++++++++++++++++ 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index bc7530264f43..6e5374da163a 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -23,13 +23,12 @@ class InputStreamTest { val instance = mock() val bytesCaptor = ArgumentCaptor.forClass(ByteArray::class.java) - val off = 1 val len = 2 val value = 3 - whenever(instance.read(bytesCaptor.capture(), eq(off), eq(len))).thenReturn(value) + whenever(instance.read(bytesCaptor.capture())).thenReturn(value) assertEquals( - api.readBytes(instance, len.toLong(), off.toLong()), + api.readBytes(instance, len.toLong()), InputStreamReadBytesResponse(value, bytesCaptor.value)) assertEquals(bytesCaptor.value.size, len) } diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart index 4f07d0732eab..8f52729672ab 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:convert'; import 'dart:typed_data'; import 'package:cross_file_android/src/android_library.g.dart' as android; @@ -201,4 +202,102 @@ void main() { expect(combineLists(await file.openRead(3, 6).toList()), [1, 1, 1]); }); }); + + test('readAsBytes', () async { + final testBytes = Uint8List.fromList([0, 1, 2]); + + final mockDocumentFile = MockDocumentFile(); + when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final mockInputStream = MockInputStream(); + when(mockInputStream.readAllBytes()).thenAnswer((_) async => testBytes); + + final mockContentResolver = MockContentResolver(); + when( + mockContentResolver.openInputStream(uri), + ).thenAnswer((_) async => mockInputStream); + android.PigeonOverrides.contentResolver_instance = mockContentResolver; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(await file.readAsBytes(), testBytes); + }); + + test('readAsString', () async { + const testString = 'Hello, World!'; + final Uint8List testBytes = utf8.encode(testString); + + final mockDocumentFile = MockDocumentFile(); + when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final mockInputStream = MockInputStream(); + when(mockInputStream.readAllBytes()).thenAnswer((_) async => testBytes); + + final mockContentResolver = MockContentResolver(); + when( + mockContentResolver.openInputStream(uri), + ).thenAnswer((_) async => mockInputStream); + android.PigeonOverrides.contentResolver_instance = mockContentResolver; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(await file.readAsString(), testString); + }); + + test('canRead', () async { + final mockDocumentFile = MockDocumentFile(); + const canRead = false; + when(mockDocumentFile.canRead()).thenAnswer((_) async => canRead); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(await file.canRead(), canRead); + }); + + test('exists', () async { + final mockDocumentFile = MockDocumentFile(); + const exists = true; + when(mockDocumentFile.exists()).thenAnswer((_) async => exists); + when(mockDocumentFile.isFile()).thenAnswer((_) async => true); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(await file.exists(), exists); + }); } From 4a84c8537a3661ac9216767fb0f6cfa0c5b3c013 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 6 Jan 2026 00:03:28 -0500 Subject: [PATCH 062/398] formatting and other stuff --- .../proxies/InputStreamTest.kt | 1 - .../lib/cross_file_android.dart | 3 + ...d_shared_storage_cross_directory_test.dart | 55 +++++++ ...ed_storage_cross_directory_test.mocks.dart | 143 ++++++++++++++++++ 4 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index 6e5374da163a..c2e0fbf959c2 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -12,7 +12,6 @@ import kotlin.test.Test import kotlin.test.assertEquals import org.mockito.ArgumentCaptor import org.mockito.kotlin.capture -import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.whenever diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 2e1a0ac21dc9..a74390acbefd 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -2,4 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' + show ListParams, PlatformXFileEntity; + export 'src/cross_file_android.dart'; diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart index 8b137891791f..b7005cbe632e 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart @@ -1 +1,56 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import 'package:cross_file_android/src/android_library.g.dart' as android; +import 'package:cross_file_android/src/android_shared_storage_cross_directory.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'android_shared_storage_cross_directory_test.mocks.dart'; + +@GenerateMocks([android.DocumentFile]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + android.PigeonOverrides.pigeon_reset(); + }); + + test('list', () async { + final mockFile = MockDocumentFile(); + const fileUri = 'fileUri'; + when(mockFile.getUri()).thenAnswer((_) async => fileUri); + when(mockFile.isFile()).thenAnswer((_) async => true); + final files = [mockFile]; + + final mockDirectory = MockDocumentFile(); + when(mockDirectory.listFiles()).thenAnswer((_) async => files); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromTreeUri = + ({required String treeUri}) { + expect(treeUri, uri); + return mockDirectory; + }; + + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, fileUri); + return mockFile; + }; + + final dir = AndroidSharedStorageXDirectory( + const PlatformSharedStorageXDirectoryCreationParams(uri: uri), + ); + + final List entityUris = await dir + .list(ListParams()) + .map((PlatformXFileEntity entity) => entity.params.uri) + .toList(); + + expect(entityUris, ['fileUri']); + }); +} diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart new file mode 100644 index 000000000000..98efe2cd15bb --- /dev/null +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart @@ -0,0 +1,143 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_android/test/android_shared_storage_cross_directory_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:cross_file_android/src/android_library.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDocumentFile_1 extends _i1.SmartFake implements _i2.DocumentFile { + _FakeDocumentFile_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [DocumentFile]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { + MockDocumentFile() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future canRead() => + (super.noSuchMethod( + Invocation.method(#canRead, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future delete() => + (super.noSuchMethod( + Invocation.method(#delete, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future exists() => + (super.noSuchMethod( + Invocation.method(#exists, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future lastModified() => + (super.noSuchMethod( + Invocation.method(#lastModified, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future length() => + (super.noSuchMethod( + Invocation.method(#length, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future isFile() => + (super.noSuchMethod( + Invocation.method(#isFile, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future isDirectory() => + (super.noSuchMethod( + Invocation.method(#isDirectory, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future> listFiles() => + (super.noSuchMethod( + Invocation.method(#listFiles, []), + returnValue: _i3.Future>.value( + <_i2.DocumentFile>[], + ), + ) + as _i3.Future>); + + @override + _i3.Future getUri() => + (super.noSuchMethod( + Invocation.method(#getUri, []), + returnValue: _i3.Future.value( + _i4.dummyValue(this, Invocation.method(#getUri, [])), + ), + ) + as _i3.Future); + + @override + _i2.DocumentFile pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeDocumentFile_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.DocumentFile); +} From 0ab90e0ac35b4d704d45e6dff09c20254598e5ff Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 6 Jan 2026 10:53:21 -0500 Subject: [PATCH 063/398] add display name support --- .../proxies/AndroidLibrary.g.kt | 25 ++++++++++++++++ .../proxies/DocumentFileProxyApi.kt | 4 +++ .../proxies/DocumentFileTest.kt | 11 +++++++ .../cross_file_android/example/lib/main.dart | 4 ++- .../cross_file_android/example/pubspec.yaml | 3 +- .../lib/cross_file_android.dart | 2 ++ .../lib/src/android_library.g.dart | 29 +++++++++++++++++++ .../android_shared_storage_cross_file.dart | 16 +++++++++- .../pigeons/android_library.dart | 3 ++ 9 files changed, 94 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index 0bac60be85c1..3836008adb39 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -582,6 +582,9 @@ abstract class PigeonApiDocumentFile( /** A Uri for the underlying document represented by this file. */ abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String + /** Returns the display name of this document. */ + abstract fun getName(pigeon_instance: androidx.documentfile.provider.DocumentFile): String? + companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { @@ -824,6 +827,28 @@ abstract class PigeonApiDocumentFile( channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.getName", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile + val wrapped: List = + try { + listOf(api.getName(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt index 2c7d8117d692..98bd941e7b25 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt @@ -60,4 +60,8 @@ class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : override fun getUri(pigeon_instance: DocumentFile): String { return pigeon_instance.uri.toString() } + + override fun getName(pigeon_instance: DocumentFile): String? { + return pigeon_instance.name + } } diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt index e70db89fa606..1d9d062bc65f 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt @@ -144,4 +144,15 @@ class DocumentFileTest { assertEquals(value.toString(), api.getUri(instance)) } + + @Test + fun getName() { + val api = TestProxyApiRegistrar().getPigeonApiDocumentFile() + + val instance = mock() + val value = "name" + whenever(instance.name).thenReturn(value) + + assertEquals(value, api.getName(instance)) + } } diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index a68fe1f42db7..c9723aa17a50 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -15,10 +15,12 @@ void integrationTestMain() { } void main() { - runApp(MaterialApp(home: FileOpenScreen())); + runApp(const MaterialApp(home: FileOpenScreen())); } +/// Example screen to open a file selector and display it. class FileOpenScreen extends StatelessWidget { + /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); Future _openFile(BuildContext context) async { diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 0b7eb717a13c..cbe5b4fca13c 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -9,7 +9,7 @@ environment: dependencies: cross_file_android: # When depending on this package from a real application you should use: - # file_selector_android: ^x.y.z + # cross_file_android: ^x.y.z # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. @@ -19,6 +19,7 @@ dependencies: sdk: flutter flutter_driver: sdk: flutter + mime: ^2.0.0 video_player: ^2.8.6 dev_dependencies: diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index a74390acbefd..e932bd8bf45e 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -5,4 +5,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show ListParams, PlatformXFileEntity; +export 'src/android_shared_storage_cross_file.dart' + show AndroidSharedStorageXFileExtension; export 'src/cross_file_android.dart'; diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index 75963c015fb0..ba08ace33382 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -965,6 +965,35 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { } } + /// Returns the display name of this document. + Future getName() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecDocumentFile; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_android.DocumentFile.getName'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as String?); + } + } + @override DocumentFile pigeon_copy() { return DocumentFile.pigeon_detached( diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index 8481c29e8350..cb0366ecfdd5 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -11,7 +11,8 @@ import 'package:flutter/foundation.dart'; import 'android_library.g.dart' as android; /// Implementation of [PlatformSharedStorageXFile] for Android. -base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { +base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile + with AndroidSharedStorageXFileExtension { /// Constructs an [AndroidSharedStorageXFile]. AndroidSharedStorageXFile(super.params) : super.implementation(); @@ -28,6 +29,9 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { @visibleForTesting static const int maxByteArrayLen = 4 * 1024; + @override + PlatformXFileEntityExtension? get extension => this; + @override Future lastModified() async { return DateTime.fromMillisecondsSinceEpoch( @@ -87,6 +91,16 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { Future exists() async { return await _documentFile.exists() && await _documentFile.isFile(); } + + @override + Future displayName() => _documentFile.getName(); +} + +/// Provides platform specific features for [AndroidSharedStorageXFile]. +mixin AndroidSharedStorageXFileExtension + implements PlatformSharedStorageXFileExtension { + /// Returns the display name of this document. + Future displayName(); } /// Error thrown when the native [android.InputStream] is not accessible. diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index 3c1181c5429a..5b9d4a99a591 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -60,6 +60,9 @@ abstract class DocumentFile { /// A Uri for the underlying document represented by this file. String getUri(); + + /// Returns the display name of this document. + String? getName(); } /// This class provides applications access to the content model. From 6a0dfbc73e43ba88a338a36a1f5140e34654b3f7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 6 Jan 2026 11:46:00 -0500 Subject: [PATCH 064/398] add name implementation to file --- .../android_shared_storage_cross_file.dart | 15 ++---------- ...d_shared_storage_cross_directory_test.dart | 19 +++++++++++++++ ...ed_storage_cross_directory_test.mocks.dart | 8 +++++++ ...ndroid_shared_storage_cross_file_test.dart | 24 ++++++++++++++++--- ..._shared_storage_cross_file_test.mocks.dart | 8 +++++++ .../cross_file_io/lib/src/io_cross_file.dart | 4 ++++ .../cross_file/cross_file_io/pubspec.yaml | 2 +- .../test/io_cross_file_test.dart | 10 ++++++-- .../lib/src/platform_cross_file.dart | 5 ++++ .../test/cross_file_platform_test.dart | 5 ++++ .../lib/src/web_cross_file.dart | 6 +++++ 11 files changed, 87 insertions(+), 19 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index cb0366ecfdd5..35d0a9e7a246 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -11,8 +11,7 @@ import 'package:flutter/foundation.dart'; import 'android_library.g.dart' as android; /// Implementation of [PlatformSharedStorageXFile] for Android. -base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile - with AndroidSharedStorageXFileExtension { +base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { /// Constructs an [AndroidSharedStorageXFile]. AndroidSharedStorageXFile(super.params) : super.implementation(); @@ -29,9 +28,6 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile @visibleForTesting static const int maxByteArrayLen = 4 * 1024; - @override - PlatformXFileEntityExtension? get extension => this; - @override Future lastModified() async { return DateTime.fromMillisecondsSinceEpoch( @@ -93,14 +89,7 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile } @override - Future displayName() => _documentFile.getName(); -} - -/// Provides platform specific features for [AndroidSharedStorageXFile]. -mixin AndroidSharedStorageXFileExtension - implements PlatformSharedStorageXFileExtension { - /// Returns the display name of this document. - Future displayName(); + Future name() => _documentFile.getName(); } /// Error thrown when the native [android.InputStream] is not accessible. diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart index b7005cbe632e..b802ea136493 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart @@ -19,6 +19,25 @@ void main() { android.PigeonOverrides.pigeon_reset(); }); + test('exists', () async { + final mockDocumentFile = MockDocumentFile(); + when(mockDocumentFile.exists()).thenAnswer((_) async => true); + when(mockDocumentFile.isDirectory()).thenAnswer((_) async => true); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromTreeUri = + ({required String treeUri}) { + expect(treeUri, uri); + return mockDocumentFile; + }; + + final file = AndroidSharedStorageXDirectory( + const PlatformSharedStorageXDirectoryCreationParams(uri: uri), + ); + + expect(await file.exists(), true); + }); + test('list', () async { final mockFile = MockDocumentFile(); const fileUri = 'fileUri'; diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart index 98efe2cd15bb..cb5504888623 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart @@ -130,6 +130,14 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { ) as _i3.Future); + @override + _i3.Future getName() => + (super.noSuchMethod( + Invocation.method(#getName, []), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + @override _i2.DocumentFile pigeon_copy() => (super.noSuchMethod( diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart index 8f52729672ab..daad742929d8 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -283,8 +283,7 @@ void main() { test('exists', () async { final mockDocumentFile = MockDocumentFile(); - const exists = true; - when(mockDocumentFile.exists()).thenAnswer((_) async => exists); + when(mockDocumentFile.exists()).thenAnswer((_) async => true); when(mockDocumentFile.isFile()).thenAnswer((_) async => true); const uri = 'uri'; @@ -298,6 +297,25 @@ void main() { const PlatformSharedStorageXFileCreationParams(uri: uri), ); - expect(await file.exists(), exists); + expect(await file.exists(), true); + }); + + test('name', () async { + final mockDocumentFile = MockDocumentFile(); + const name = 'name'; + when(mockDocumentFile.getName()).thenAnswer((_) async => name); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = + ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final file = AndroidSharedStorageXFile( + const PlatformSharedStorageXFileCreationParams(uri: uri), + ); + + expect(await file.name(), name); }); } diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart index e9d0eefc32f2..6d769a543149 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart @@ -189,6 +189,14 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { ) as _i3.Future); + @override + _i3.Future getName() => + (super.noSuchMethod( + Invocation.method(#getName, []), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + @override _i2.DocumentFile pigeon_copy() => (super.noSuchMethod( diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index c8cf3a90edb9..786248f072d5 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -7,6 +7,7 @@ import 'dart:io'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; +import 'package:path/path.dart' as path; /// Implementation of [PlatformXFileCreationParams] for dart:io. @immutable @@ -67,6 +68,9 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { @override Future exists() async => file.existsSync(); + + @override + Future name() async => path.basename(file.path); } /// Provides platform specific features for [IOXFile]. diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index d00cebceb58f..c59681ad1d38 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -13,11 +13,11 @@ dependencies: path: ../cross_file_platform_interface flutter: sdk: flutter + path: ^1.9.1 dev_dependencies: flutter_test: sdk: flutter - path: ^1.9.1 topics: - files diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index 4048de649d12..18548ad1ddf0 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -51,8 +51,6 @@ void main() { PlatformXFileCreationParams(uri: testFile.path), ); - print(await file.readAsBytes()); - expect(await file.readAsBytes(), await testFile.readAsBytes()); }); @@ -79,5 +77,13 @@ void main() { expect(await file.exists(), testFile.existsSync()); }); + + test('name', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.name(), 'test_file.txt'); + }); }); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 41ca0176dcd3..12d697cd6195 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -131,4 +131,9 @@ abstract base class PlatformXFile extends PlatformXFileEntity { /// Platforms may throw an exception if there is an error opening or reading /// the resource. Future readAsString({Encoding encoding = utf8}); + + /// The name of the resource represented by this object. + /// + /// The path is excluded from this value. + Future name(); } diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 5319a9cf71fe..f43aabebac7a 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -71,4 +71,9 @@ final class TestXFile extends PlatformXFile { Future readAsString({Encoding encoding = utf8}) { throw UnimplementedError(); } + + @override + Future name() { + throw UnimplementedError(); + } } diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index b9710252e8da..acf27d9b9d6c 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -130,6 +130,12 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { downloadObjectUrl(params.uri, name); } + + @override + Future name() async { + final Blob blob = await getBlob(); + return blob is File ? blob.name : null; + } } /// Provides platform specific features for [WebXFile]. From 46f56fc63fe2f704a36e8e8032d75be9e59d8e60 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 12:16:59 -0500 Subject: [PATCH 065/398] implement cross_file --- .../cross_file/lib/src/cross_file.dart | 102 +++++++++++++++--- .../cross_file/lib/src/cross_file_entity.dart | 22 ++++ .../lib/src/shared_storage_cross_file.dart | 64 +++++++++-- 3 files changed, 165 insertions(+), 23 deletions(-) create mode 100644 packages/cross_file/cross_file/lib/src/cross_file_entity.dart diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 2d16a758ee1b..e4d60330f383 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -1,57 +1,129 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'dart:convert'; import 'dart:typed_data'; -import 'package:flutter/foundation.dart' show immutable; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:meta/meta.dart'; +import 'cross_file_entity.dart'; + +/// A reference to a local data resource. +/// +/// ## Platform-Specific Features +/// This class contains an underlying implementation provided by the current +/// platform. Once a platform implementation is imported, the examples below +/// can be followed to use features provided by a platform's implementation. +/// +/// {@macro cross_file.XFile.fromPlatformCreationParams} +/// +/// Below is an example of accessing the platform-specific extension for +/// the dart:io implementation of `cross_file`: +/// +/// ```dart +/// final XFile file = XFile('my/file.txt'); +/// +/// final IOXFileExtension? ioExtension = file.maybeGetPlatformExtension(); +/// if (ioExtension != null) { +/// print(ioExtension.file.path); +/// } +/// ``` @immutable -@optionalTypeArgs -class XFile { +class XFile extends XFileEntity { + /// Constructs a [XFile]. + /// + /// See [XFile.fromPlatformCreationParams] for setting parameters for a + /// specific platform. XFile(String uri) : this.fromPlatformCreationParams(PlatformXFileCreationParams(uri: uri)); + /// Constructs an [XFile] from creation params for a specific platform. + /// + /// {@template cross_file.XFile.fromPlatformCreationParams} + /// Below is an example of setting platform-specific creation parameters for + /// the dart:io implementation of `cross_file`: + /// + /// ```dart + /// var params = const PlatformXFileCreationParams(uri: 'my/file.txt'); + /// + /// if (CrossFilePlatform.instance is CrossFileIO) { + /// params = IOXFileCreationParams.fromCreationParams( + /// params, + /// ); + /// } + /// + /// final file = XFile.fromCreationParams(params); + /// ``` + /// {@endtemplate} XFile.fromPlatformCreationParams(PlatformXFileCreationParams params) : this.fromPlatform(PlatformXFile(params)); - XFile.fromPlatform(this.platform); + /// Constructs a [XFile] from a specific platform implementation. + const XFile.fromPlatform(PlatformXFile super.platform); - final PlatformXFile platform; - - String get uri => platform.params.uri; + /// Implementation of [XFile] for the current platform. + @override + PlatformXFile get platform => super.platform as PlatformXFile; /// Provides a nonnull platform class extension. /// /// Will throw an exception if the specified platform extension can not be /// returned. - S getPlatformExtension() { + S getPlatformExtension() { return platform.extension! as S; } /// Attempt to provide the platform class extension. /// /// Returns null if the specified platform extension cannot be retrieved. - S? maybeGetPlatformExtension() { + S? maybeGetPlatformExtension() { return platform.extension is S ? platform.extension! as S : null; } + /// Date and time when the resource was last modified, if the information is + /// available. + /// + /// Platforms may throw an exception if the information is not available. Future lastModified() => platform.lastModified(); - /// The length of the file. + /// The length of the data represented by this uri, in bytes. + /// + /// Platforms may throw an exception if the information is not available. Future length() => platform.length(); - /// Whether file exists. - Future exists() => platform.exists(); - + /// Whether the resource represented by this reference can be read. Future canRead() => platform.canRead(); + /// Creates a new independent Stream for the contents of this resource. + /// + /// If start is present, the file will be read from byte-offset start. + /// Otherwise from the beginning (index 0). + /// + /// If end is present, only bytes up to byte-index end will be read. + /// Otherwise, until end of file. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. Stream> openRead([int? start, int? end]) => platform.openRead(start, end); - /// Reads the entire file contents as a list of bytes. + /// Reads the entire resource contents as a list of bytes. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. Future readAsBytes() => platform.readAsBytes(); - /// Reads the entire file contents as a string using the given Encoding. + /// Reads the entire resource contents as a string using the given Encoding. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. Future readAsString({Encoding encoding = utf8}) => platform.readAsString(encoding: encoding); + + /// The name of the resource represented by this object. + /// + /// The path is excluded from this value. + Future name() => platform.name(); } diff --git a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart new file mode 100644 index 000000000000..4c5d271d80f8 --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:meta/meta.dart'; + +/// The common superclass for [XFile] and [XDirectory]. +@immutable +abstract class XFileEntity { + /// Constructs a [XFileEntity]. + const XFileEntity(this.platform); + + /// Implementation of [XFileEntity] for the current platform. + final PlatformXFileEntity platform; + + /// A string used to reference the resource's location. + String get uri => platform.params.uri; + + /// Whether the resource represented by this reference exists. + Future exists() => platform.exists(); +} diff --git a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart index 64f1b5b445df..b364046ff6a6 100644 --- a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart @@ -1,24 +1,72 @@ -import 'package:flutter/foundation.dart' show immutable; +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart' show immutable; import 'cross_file.dart'; +/// A reference to a local data resource within a devices scoped storage. +/// +/// ## Platform-Specific Features +/// This class contains an underlying implementation provided by the current +/// platform. Once a platform implementation is imported, the examples below +/// can be followed to use features provided by a platform's implementation. +/// +/// {@macro cross_file.XFile.fromPlatformCreationParams} +/// +/// Below is an example of accessing the platform-specific extension for +/// the Android implementation of `cross_file`: +/// +/// ```dart +/// final SharedStorageXFile file = XFile('my/file.txt'); +/// +/// final AndroidSharedStorageXFileExtension? androidExtension = +/// file.maybeGetPlatformExtension(); +/// if (androidExtension != null) { +/// print(androidExtension.file.path); +/// } +/// ``` @immutable -class SharedStorageXFile extends XFile { - SharedStorageXFile(String path) +class SharedStorageXFile extends XFile { + /// Constructs a [SharedStorageXFile]. + /// + /// See [SharedStorageXFile.fromPlatformCreationParams] for setting parameters + /// for a specific platform. + SharedStorageXFile(String uri) : this.fromPlatformCreationParams( - PlatformSharedStorageXFileCreationParams(path: path), + PlatformSharedStorageXFileCreationParams(uri: uri), ); + /// Constructs a [SharedStorageXFile] from creation params for a specific + /// platform. + /// + /// {@template cross_file.SharedStorageXFile.fromPlatformCreationParams} + /// Below is an example of setting platform-specific creation parameters for + /// the Android implementation of `cross_file`: + /// + /// ```dart + /// var params = const PlatformXFileCreationParams(uri: 'my/file.txt'); + /// + /// if (CrossFilePlatform.instance is CrossFileAndroid) { + /// params = AndroidSharedStorageXFileCreationParams.fromCreationParams( + /// params, + /// ); + /// } + /// + /// final file = SharedStorageXFile.fromCreationParams(params); + /// ``` + /// {@endtemplate} SharedStorageXFile.fromPlatformCreationParams( PlatformSharedStorageXFileCreationParams params, ) : this.fromPlatform(PlatformSharedStorageXFile(params)); - SharedStorageXFile.fromPlatform(this.platform) : super.fromPlatform(platform); + /// Constructs a [SharedStorageXFile] from a specific platform implementation. + const SharedStorageXFile.fromPlatform(PlatformSharedStorageXFile super.platform) + : super.fromPlatform(); @override - final PlatformSharedStorageXFile platform; - - Future delete() => platform.delete(); + PlatformSharedStorageXFile get platform => + super.platform as PlatformSharedStorageXFile; } From 47079317b4de4500b07e918ff45b407175c4bd41 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 12:41:20 -0500 Subject: [PATCH 066/398] update web impl example app --- packages/cross_file/cross_file_web/README.md | 20 +-- .../cross_file_web/example/.gitignore | 45 ------- .../cross_file_web/example/README.md | 24 ++-- .../example/analysis_options.yaml | 28 ---- .../cross_file_web/example/lib/main.dart | 122 ++++++++++++------ .../cross_file_web/example/pubspec.yaml | 83 ++---------- .../example/test/widget_test.dart | 27 ---- 7 files changed, 114 insertions(+), 235 deletions(-) delete mode 100644 packages/cross_file/cross_file_web/example/.gitignore delete mode 100644 packages/cross_file/cross_file_web/example/analysis_options.yaml delete mode 100644 packages/cross_file/cross_file_web/example/test/widget_test.dart diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md index a89013f88dc9..315574218feb 100644 --- a/packages/cross_file/cross_file_web/README.md +++ b/packages/cross_file/cross_file_web/README.md @@ -1,15 +1,15 @@ -# cross_file_web +# cross\_file\_web -A new Flutter plugin project. +The web implementation of [`cross_file`][1]. -## Getting Started +## Usage -This project is a starting point for a Flutter -[plug-in package](https://flutter.dev/to/develop-plugins), -a specialized package that includes platform-specific implementation code for -Android and/or iOS. +This package is [endorsed][2], which means you can simply use `cross_file` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. +[1]: https://pub.dev/packages/cross_file +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/packages/cross_file/cross_file_web/example/.gitignore b/packages/cross_file/cross_file_web/example/.gitignore deleted file mode 100644 index 3820a95c65c3..000000000000 --- a/packages/cross_file/cross_file_web/example/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/packages/cross_file/cross_file_web/example/README.md b/packages/cross_file/cross_file_web/example/README.md index a4d1dc0858ef..932e9f227cbe 100644 --- a/packages/cross_file/cross_file_web/example/README.md +++ b/packages/cross_file/cross_file_web/example/README.md @@ -1,17 +1,19 @@ -# cross_file_web_example +# Platform Implementation Test App -Demonstrates how to use the cross_file_web plugin. +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. -## Getting Started +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. -This project is a starting point for a Flutter application. +## Testing -A few resources to get you started if this is your first Flutter project: +This package uses `package:integration_test` to run its tests in a web browser. -- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) -- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) +See [Plugin Tests > Web Tests](https://github.com/flutter/flutter/blob/master/docs/ecosystem/testing/Plugin-Tests.md#web-tests) +in the Flutter documentation for instructions to set up and run the tests in this package. -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +Check [flutter.dev > Integration testing](https://docs.flutter.dev/testing/integration-tests) +for more info. diff --git a/packages/cross_file/cross_file_web/example/analysis_options.yaml b/packages/cross_file/cross_file_web/example/analysis_options.yaml deleted file mode 100644 index 0d2902135cae..000000000000 --- a/packages/cross_file/cross_file_web/example/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index 99ec34c5a563..c66ed1242f9c 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -1,59 +1,101 @@ -import 'package:flutter/material.dart'; -import 'dart:async'; +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -import 'package:flutter/services.dart'; -import 'package:cross_file_web/cross_file_web.dart'; +import 'package:file_selector/file_selector.dart'; +import 'package:flutter/material.dart'; +import 'package:mime/mime.dart' as mime; void main() { - runApp(const MyApp()); + runApp(const MaterialApp(home: FileOpenScreen())); } -class MyApp extends StatefulWidget { - const MyApp({super.key}); +/// Example screen to open a file selector and display it. +class FileOpenScreen extends StatelessWidget { + /// Constructs a [FileOpenScreen]. + const FileOpenScreen({super.key}); - @override - State createState() => _MyAppState(); -} + Future _openFile(BuildContext context) async { + final XFile? file = await openFile(); -class _MyAppState extends State { - String _platformVersion = 'Unknown'; - final _crossFileWebPlugin = CrossFileWeb(); + if (!context.mounted) { + return; + } - @override - void initState() { - super.initState(); - initPlatformState(); + if (file case final XFile file) { + switch (mime.lookupMimeType(file.path)) { + case final String mimeType when mimeType.startsWith('text'): + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(file), + ); + case final String mimeType when mimeType.startsWith('image'): + case final String mimeType when mimeType.startsWith('application'): + case null: + debugPrint('Unsupported file type: ${file.path}'); + return; + } + } } - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - String platformVersion; - // Platform messages may fail, so we use a try/catch PlatformException. - // We also handle the message potentially returning null. - try { - platformVersion = - await _crossFileWebPlugin.getPlatformVersion() ?? 'Unknown platform version'; - } on PlatformException { - platformVersion = 'Failed to get platform version.'; - } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a File'), + backgroundColor: Colors.blue, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ], + ), + ), + ); + } +} - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.file, {super.key}); - setState(() { - _platformVersion = platformVersion; - }); - } + /// The file. + final XFile file; @override Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar(title: const Text('Plugin example app')), - body: Center(child: Text('Running on: $_platformVersion\n')), + return AlertDialog( + title: Text(file.path), + content: Scrollbar( + child: SingleChildScrollView( + child: FutureBuilder( + future: file.readAsString(), + builder: (_, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!); + } else { + return const CircularProgressIndicator(); + } + }, + ), + ), ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], ); } } diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index 44af8c0ae955..55f86e8150e1 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -1,85 +1,20 @@ name: cross_file_web_example -description: "Demonstrates how to use the cross_file_web plugin." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: none environment: - sdk: ^3.11.0-169.0.dev + sdk: ^3.8.0 + flutter: ">=3.32.0" -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: + file_selector: + path: ../../../file_selector/file_selector flutter: sdk: flutter - - cross_file_web: - # When depending on this package from a real application you should use: - # cross_file_web: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^1.0.8 + mime: ^2.0.0 + web: ^1.0.0 dev_dependencies: - integration_test: - sdk: flutter flutter_test: sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package + integration_test: + sdk: flutter diff --git a/packages/cross_file/cross_file_web/example/test/widget_test.dart b/packages/cross_file/cross_file_web/example/test/widget_test.dart deleted file mode 100644 index 538ffd75ff13..000000000000 --- a/packages/cross_file/cross_file_web/example/test/widget_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:cross_file_web_example/main.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is Text && widget.data!.startsWith('Running on:'), - ), - findsOneWidget, - ); - }); -} From 1dfee637540ede1518b5f5b962b17a1a5422ffb4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 12:59:58 -0500 Subject: [PATCH 067/398] fix registrar --- packages/cross_file/cross_file_web/lib/cross_file_web.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 0a1efc6f88aa..049606e08a8d 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -5,6 +5,7 @@ export 'src/cross_file_web.dart'; export 'src/web_cross_file.dart' show + WebXFile, BlobWebXFileCreationParams, UrlWebXFileCreationParams, WebXFileCreationParams, From f03e7fc54f6c20e9543907d8e48e7e395c396443 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 13:04:40 -0500 Subject: [PATCH 068/398] actual fix --- packages/cross_file/cross_file_web/lib/cross_file_web.dart | 1 - packages/cross_file/cross_file_web/lib/src/cross_file_web.dart | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 049606e08a8d..0a1efc6f88aa 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -5,7 +5,6 @@ export 'src/cross_file_web.dart'; export 'src/web_cross_file.dart' show - WebXFile, BlobWebXFileCreationParams, UrlWebXFileCreationParams, WebXFileCreationParams, diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart index d1dcfb0f8c74..b09e3cb0ee7c 100644 --- a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -3,13 +3,14 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'web_cross_file.dart'; /// Implementation of [CrossFilePlatform] for web. base class CrossFileWeb extends CrossFilePlatform { /// Registers this class as the default instance of [CrossFilePlatform]. - static void registerWith() { + static void registerWith(Registrar registrar) { CrossFilePlatform.instance = CrossFileWeb(); } From 767a77074c212f7f324e5909aa13ea74c6a8b17b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 14:55:21 -0500 Subject: [PATCH 069/398] web unit tests --- .../cross_file/cross_file_web/pubspec.yaml | 2 - .../cross_file_web_method_channel_test.dart | 26 ---- .../test/cross_file_web_test.dart | 28 ---- .../test/web_cross_file_test.dart | 132 ++++++++++++++++++ 4 files changed, 132 insertions(+), 56 deletions(-) delete mode 100644 packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart delete mode 100644 packages/cross_file/cross_file_web/test/cross_file_web_test.dart create mode 100644 packages/cross_file/cross_file_web/test/web_cross_file_test.dart diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 9268d4643826..7468d0ae0992 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -26,10 +26,8 @@ dependencies: path: ../cross_file_platform_interface dev_dependencies: - build_runner: ^2.1.5 flutter_test: sdk: flutter - mockito: ^5.4.4 topics: - file \ No newline at end of file diff --git a/packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart b/packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart deleted file mode 100644 index a1d82ae50459..000000000000 --- a/packages/cross_file/cross_file_web/test/cross_file_web_method_channel_test.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_web/cross_file_web_method_channel.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - MethodChannelCrossFileWeb platform = MethodChannelCrossFileWeb(); - const MethodChannel channel = MethodChannel('cross_file_web'); - - setUp(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(channel, (MethodCall methodCall) async { - return '42'; - }); - }); - - tearDown(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(channel, null); - }); - - test('getPlatformVersion', () async { - expect(await platform.getPlatformVersion(), '42'); - }); -} diff --git a/packages/cross_file/cross_file_web/test/cross_file_web_test.dart b/packages/cross_file/cross_file_web/test/cross_file_web_test.dart deleted file mode 100644 index 58ce71b18e7f..000000000000 --- a/packages/cross_file/cross_file_web/test/cross_file_web_test.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_web/cross_file_web.dart'; -import 'package:cross_file_web/cross_file_web_platform_interface.dart'; -import 'package:cross_file_web/cross_file_web_method_channel.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -class MockCrossFileWebPlatform - with MockPlatformInterfaceMixin - implements CrossFileWebPlatform { - @override - Future getPlatformVersion() => Future.value('42'); -} - -void main() { - final CrossFileWebPlatform initialPlatform = CrossFileWebPlatform.instance; - - test('$MethodChannelCrossFileWeb is the default instance', () { - expect(initialPlatform, isInstanceOf()); - }); - - test('getPlatformVersion', () async { - CrossFileWeb crossFileWebPlugin = CrossFileWeb(); - MockCrossFileWebPlatform fakePlatform = MockCrossFileWebPlatform(); - CrossFileWebPlatform.instance = fakePlatform; - - expect(await crossFileWebPlugin.getPlatformVersion(), '42'); - }); -} diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart new file mode 100644 index 000000000000..f27cd9f57567 --- /dev/null +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -0,0 +1,132 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@TestOn('chrome') // Uses web-only Flutter SDK +library; + +import 'dart:convert'; +import 'dart:js_interop'; +import 'dart:typed_data'; + +import 'package:cross_file_web/src/web_cross_file.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:web/web.dart' as html; + +const String expectedStringContents = 'Hello, world! I ❤ ñ! 空手'; +final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); +final html.File textFile = html.File( + [bytes.toJS].toJS, + 'hello.txt', +); +final String textFileUrl = html.URL.createObjectURL(textFile as JSObject); + +void main() { + group('Create with an objectUrl', () { + final file = WebXFile(UrlWebXFileCreationParams(objectUrl: textFileUrl)); + + test('Can be read as a string', () async { + expect(await file.readAsString(), equals(expectedStringContents)); + }); + + test('Can be read as bytes', () async { + expect(await file.readAsBytes(), equals(bytes)); + }); + + test('Can be read as a stream', () async { + expect(await file.openRead().first, equals(bytes)); + }); + + test('Stream can be sliced', () async { + expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); + }); + }); + + group('Blob backend', () { + final file = WebXFile(BlobWebXFileCreationParams(textFile)); + + test('Stores data as a Blob', () async { + // Read the blob from its path 'natively' + final html.Response response = await html.window + .fetch(file.params.uri.toJS) + .toDart; + + final JSAny arrayBuffer = await response.arrayBuffer().toDart; + final ByteBuffer data = (arrayBuffer as JSArrayBuffer).toDart; + expect(data.asUint8List(), equals(bytes)); + }); + + test('Data may be purged from the blob!', () async { + html.URL.revokeObjectURL(file.params.uri); + + final urlFile = WebXFile( + UrlWebXFileCreationParams(objectUrl: file.params.uri), + ); + + await expectLater(() => urlFile.readAsString(), throwsException); + }); + }); + + group('download', () { + const crossFileDomElementId = '__x_file_dom_element'; + + group('XFile download', () { + test('creates a DOM container', () async { + final file = WebXFile(BlobWebXFileCreationParams(textFile)); + + await file.download(''); + + final html.Element? container = html.document.querySelector( + '#$crossFileDomElementId', + ); + + expect(container, isNotNull); + }); + + test('create anchor element', () async { + final file = WebXFile(BlobWebXFileCreationParams(textFile)); + + await file.download('path'); + + final html.Element container = html.document.querySelector( + '#$crossFileDomElementId', + )!; + + late html.HTMLAnchorElement element; + for (var i = 0; i < container.childNodes.length; i++) { + final html.Element test = container.children.item(i)!; + if (test.tagName == 'A') { + element = test as html.HTMLAnchorElement; + break; + } + } + + // if element is not found, the `firstWhere` call will throw StateError. + expect(element.href, file.params.uri); + expect(element.download, 'path'); + }); + + // test('anchor element is clicked', () async { + // final mockAnchor = + // html.document.createElement('a') as html.HTMLAnchorElement; + // + // final overrides = CrossFileTestOverrides( + // createAnchorElement: (_, __) => mockAnchor, + // ); + // + // final file = XFile.fromData( + // bytes, + // name: textFile.name, + // overrides: overrides, + // ); + // + // var clicked = false; + // mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); + // + // await file.saveTo('path'); + // + // expect(clicked, true); + // }); + }); + }); +} From eb7b6d99f588f640a3ef156128ef5bbc1f8f0749 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:19:11 -0500 Subject: [PATCH 070/398] test overrides --- .../lib/src/web_cross_file.dart | 21 +++++++--- .../cross_file_web/lib/src/web_helpers.dart | 25 ++++++++++- .../test/web_cross_file_test.dart | 41 +++++++++---------- 3 files changed, 58 insertions(+), 29 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index acf27d9b9d6c..cf2d307158c3 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -14,23 +14,32 @@ import 'web_helpers.dart'; @immutable sealed class WebXFileCreationParams extends PlatformXFileCreationParams { /// Constructs a [WebXFileCreationParams]. - const WebXFileCreationParams({required super.uri}); + const WebXFileCreationParams({required super.uri, this.testOverrides}); + + /// Overrides some functions to allow testing. + @visibleForTesting + final XFileTestOverrides? testOverrides; } /// Implementation of [WebXFileCreationParams] with an object url. @immutable base class UrlWebXFileCreationParams extends WebXFileCreationParams { /// Constructs a [UrlWebXFileCreationParams]. - const UrlWebXFileCreationParams({required String objectUrl}) - : super(uri: objectUrl); + const UrlWebXFileCreationParams({ + required String objectUrl, + @visibleForTesting super.testOverrides, + }) : super(uri: objectUrl); } /// Implementation of [WebXFileCreationParams] with a [Blob]. @immutable base class BlobWebXFileCreationParams extends WebXFileCreationParams { /// Constructs a [BlobWebXFileCreationParams]. - BlobWebXFileCreationParams(this.blob, {this.autoRevokeObjectUrl = true}) - : super(uri: URL.createObjectURL(blob)) { + BlobWebXFileCreationParams( + this.blob, { + this.autoRevokeObjectUrl = true, + @visibleForTesting super.testOverrides, + }) : super(uri: URL.createObjectURL(blob)) { if (autoRevokeObjectUrl) { _finalizer.attach(this, uri); } @@ -128,7 +137,7 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { name = blob.name; } - downloadObjectUrl(params.uri, name); + downloadObjectUrl(params.uri, name, testOverrides: params.testOverrides); } @override diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index 7ad0a513e6d7..3ed682282f43 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -5,6 +5,7 @@ import 'dart:js_interop'; import 'dart:typed_data'; +import 'package:flutter/foundation.dart'; import 'package:web/web.dart'; /// Create anchor element with download attribute @@ -40,11 +41,20 @@ Element ensureInitialized(String id) { /// the file to whatever they want before it's actually saved. /// /// Maybe some day: https://developer.mozilla.org/en-US/docs/Web/API/Window/showSaveFilePicker -void downloadObjectUrl(String objectUrl, String? name) { +void downloadObjectUrl( + String objectUrl, + String? name, { + XFileTestOverrides? testOverrides, +}) { // Create a DOM container where the anchor can be injected. final Element target = ensureInitialized('__x_file_dom_element'); + // Create an tag with the appropriate download attributes and click it - final HTMLAnchorElement element = createAnchorElement(objectUrl, name); + // May be overridden with CrossFileTestOverrides + final HTMLAnchorElement element = testOverrides != null + ? testOverrides.createAnchorElement(objectUrl, name) as HTMLAnchorElement + : createAnchorElement(objectUrl, name); + // Clear the children in target. target.replaceChildren(JSArray()); // Add the new `element` and click. @@ -83,3 +93,14 @@ Future fetchBlob(String objectUrl) async { throw Exception('Could not fetch Blob by URL: $objectUrl'); } } + +/// Overrides some functions to allow testing. +// TODO(dit): https://github.com/flutter/flutter/issues/91400 +// Move this to web_helpers_test.dart +class XFileTestOverrides { + /// Default constructor for overrides + XFileTestOverrides({required this.createAnchorElement}); + + /// For overriding the creation of the file input element. + Element Function(String href, String? suggestedName) createAnchorElement; +} diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index f27cd9f57567..7145e62900e0 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -10,6 +10,7 @@ import 'dart:js_interop'; import 'dart:typed_data'; import 'package:cross_file_web/src/web_cross_file.dart'; +import 'package:cross_file_web/src/web_helpers.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:web/web.dart' as html; @@ -106,27 +107,25 @@ void main() { expect(element.download, 'path'); }); - // test('anchor element is clicked', () async { - // final mockAnchor = - // html.document.createElement('a') as html.HTMLAnchorElement; - // - // final overrides = CrossFileTestOverrides( - // createAnchorElement: (_, __) => mockAnchor, - // ); - // - // final file = XFile.fromData( - // bytes, - // name: textFile.name, - // overrides: overrides, - // ); - // - // var clicked = false; - // mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); - // - // await file.saveTo('path'); - // - // expect(clicked, true); - // }); + test('anchor element is clicked', () async { + final mockAnchor = + html.document.createElement('a') as html.HTMLAnchorElement; + + final testOverrides = XFileTestOverrides( + createAnchorElement: (_, __) => mockAnchor, + ); + + final file = WebXFile( + BlobWebXFileCreationParams(textFile, testOverrides: testOverrides), + ); + + var clicked = false; + mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); + + await file.download('path'); + + expect(clicked, true); + }); }); }); } From 317702cb6ce93e611b38c8edefcaef8ffd8287f3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 15:21:43 -0500 Subject: [PATCH 071/398] fix integration test --- .../plugin_integration_test.dart | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart index bf7a4cd61995..621977be68c7 100644 --- a/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart +++ b/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart @@ -1,24 +1,14 @@ -// This is a basic Flutter integration test. -// -// Since integration tests run in a full Flutter application, they can interact -// with the host side of a plugin implementation, unlike Dart unit tests. -// -// For more information about Flutter integration tests, please see -// https://flutter.dev/to/integration-testing +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:cross_file_web/cross_file_web.dart'; - void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('getPlatformVersion test', (WidgetTester tester) async { - final CrossFileWeb plugin = CrossFileWeb(); - final String? version = await plugin.getPlatformVersion(); - // The version string depends on the host platform running the test, so - // just assert that some non-empty string is returned. - expect(version?.isNotEmpty, true); - }); + // Since this test is lacking integration tests, this test ensures the example + // app can be launched on an emulator/device. + testWidgets('Launch Test', (WidgetTester tester) async {}); } From 6933d775cb6dc2aa8b3a5d2c0ad97a6f53df24a6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 7 Jan 2026 16:55:27 -0500 Subject: [PATCH 072/398] some license stuff --- .../cross_file_android/example/README.md | 21 +++++---------- .../cross_file/cross_file_web/CHANGELOG.md | 2 +- packages/cross_file/cross_file_web/LICENSE | 26 ++++++++++++++++++- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/README.md b/packages/cross_file/cross_file_android/example/README.md index 18ce85271cd6..96b8bb17dbff 100644 --- a/packages/cross_file/cross_file_android/example/README.md +++ b/packages/cross_file/cross_file_android/example/README.md @@ -1,16 +1,9 @@ -# cross_file_android_example +# Platform Implementation Test App -Demonstrates how to use the cross_file_android plugin. +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/packages/cross_file/cross_file_web/CHANGELOG.md b/packages/cross_file/cross_file_web/CHANGELOG.md index 41cc7d8192ec..d0bd041d0ff6 100644 --- a/packages/cross_file/cross_file_web/CHANGELOG.md +++ b/packages/cross_file/cross_file_web/CHANGELOG.md @@ -1,3 +1,3 @@ ## 0.0.1 -* TODO: Describe initial release. +* Initial release. diff --git a/packages/cross_file/cross_file_web/LICENSE b/packages/cross_file/cross_file_web/LICENSE index ba75c69f7f21..29b709dac6c7 100644 --- a/packages/cross_file/cross_file_web/LICENSE +++ b/packages/cross_file/cross_file_web/LICENSE @@ -1 +1,25 @@ -TODO: Add your license here. +Copyright 2013 The Flutter Authors + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 5bda1d90655a95223900d99b407d4ae407be5d36 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 9 Jan 2026 14:14:29 -0500 Subject: [PATCH 073/398] initial commit darwin impl --- .../cross_file/cross_file_darwin/.gitignore | 33 + .../cross_file/cross_file_darwin/.metadata | 33 + .../cross_file/cross_file_darwin/CHANGELOG.md | 3 + packages/cross_file/cross_file_darwin/LICENSE | 1 + .../cross_file/cross_file_darwin/README.md | 15 + .../cross_file_darwin/analysis_options.yaml | 4 + .../cross_file_darwin/darwin/.gitignore | 38 + .../Classes/CrossFileDarwinPlugin.swift | 36 + .../darwin/Resources/PrivacyInfo.xcprivacy | 14 + .../darwin/cross_file_darwin.podspec | 37 + .../cross_file_darwin/example/.gitignore | 45 ++ .../cross_file_darwin/example/README.md | 17 + .../example/analysis_options.yaml | 28 + .../plugin_integration_test.dart | 24 + .../cross_file_darwin/example/ios/.gitignore | 34 + .../ios/Flutter/AppFrameworkInfo.plist | 24 + .../example/ios/Flutter/Debug.xcconfig | 1 + .../example/ios/Flutter/Release.xcconfig | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 623 ++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 101 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 16 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../example/ios/Runner/Info.plist | 70 ++ .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/ios/Runner/SceneDelegate.swift | 6 + .../example/ios/RunnerTests/RunnerTests.swift | 27 + .../cross_file_darwin/example/lib/main.dart | 59 ++ .../example/macos/.gitignore | 7 + .../macos/Flutter/Flutter-Debug.xcconfig | 1 + .../macos/Flutter/Flutter-Release.xcconfig | 1 + .../macos/Runner.xcodeproj/project.pbxproj | 705 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 99 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../example/macos/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2218 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 +++++++++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../example/macos/Runner/Release.entitlements | 8 + .../macos/RunnerTests/RunnerTests.swift | 28 + .../cross_file_darwin/example/pubspec.yaml | 85 +++ .../example/test/widget_test.dart | 27 + .../lib/cross_file_darwin.dart | 8 + .../lib/cross_file_darwin_method_channel.dart | 19 + .../cross_file_darwin_platform_interface.dart | 29 + .../cross_file/cross_file_darwin/pubspec.yaml | 73 ++ ...cross_file_darwin_method_channel_test.dart | 26 + .../test/cross_file_darwin_test.dart | 28 + 90 files changed, 3231 insertions(+) create mode 100644 packages/cross_file/cross_file_darwin/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/.metadata create mode 100644 packages/cross_file/cross_file_darwin/CHANGELOG.md create mode 100644 packages/cross_file/cross_file_darwin/LICENSE create mode 100644 packages/cross_file/cross_file_darwin/README.md create mode 100644 packages/cross_file/cross_file_darwin/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_darwin/darwin/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/Resources/PrivacyInfo.xcprivacy create mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec create mode 100644 packages/cross_file/cross_file_darwin/example/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/example/README.md create mode 100644 packages/cross_file/cross_file_darwin/example/analysis_options.yaml create mode 100644 packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart create mode 100644 packages/cross_file/cross_file_darwin/example/ios/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/AppDelegate.swift create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Info.plist create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/SceneDelegate.swift create mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/cross_file/cross_file_darwin/example/lib/main.dart create mode 100644 packages/cross_file/cross_file_darwin/example/macos/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/AppDelegate.swift create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Info.plist create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/MainFlutterWindow.swift create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements create mode 100644 packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift create mode 100644 packages/cross_file/cross_file_darwin/example/pubspec.yaml create mode 100644 packages/cross_file/cross_file_darwin/example/test/widget_test.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart create mode 100644 packages/cross_file/cross_file_darwin/pubspec.yaml create mode 100644 packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart diff --git a/packages/cross_file/cross_file_darwin/.gitignore b/packages/cross_file/cross_file_darwin/.gitignore new file mode 100644 index 000000000000..b9d7f25b91b6 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/.gitignore @@ -0,0 +1,33 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +.flutter-plugins-dependencies +/build/ +/coverage/ diff --git a/packages/cross_file/cross_file_darwin/.metadata b/packages/cross_file/cross_file_darwin/.metadata new file mode 100644 index 000000000000..80c51c8a98e1 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/.metadata @@ -0,0 +1,33 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "08e122f466ea6b49c266bb09869618d9e50a0119" + channel: "main" + +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 + base_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 + - platform: ios + create_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 + base_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 + - platform: macos + create_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 + base_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_darwin/CHANGELOG.md b/packages/cross_file/cross_file_darwin/CHANGELOG.md new file mode 100644 index 000000000000..41cc7d8192ec --- /dev/null +++ b/packages/cross_file/cross_file_darwin/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_darwin/LICENSE b/packages/cross_file/cross_file_darwin/LICENSE new file mode 100644 index 000000000000..ba75c69f7f21 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/packages/cross_file/cross_file_darwin/README.md b/packages/cross_file/cross_file_darwin/README.md new file mode 100644 index 000000000000..e7b7591898d1 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/README.md @@ -0,0 +1,15 @@ +# cross_file_darwin + +A new Flutter plugin project. + +## Getting Started + +This project is a starting point for a Flutter +[plug-in package](https://flutter.dev/to/develop-plugins), +a specialized package that includes platform-specific implementation code for +Android and/or iOS. + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev), which offers tutorials, +samples, guidance on mobile development, and a full API reference. + diff --git a/packages/cross_file/cross_file_darwin/analysis_options.yaml b/packages/cross_file/cross_file_darwin/analysis_options.yaml new file mode 100644 index 000000000000..a5744c1cfbe7 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_darwin/darwin/.gitignore b/packages/cross_file/cross_file_darwin/darwin/.gitignore new file mode 100644 index 000000000000..034771fc9c9b --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/.gitignore @@ -0,0 +1,38 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +.DS_Store +*.swp +profile + +DerivedData/ +build/ +GeneratedPluginRegistrant.h +GeneratedPluginRegistrant.m + +.generated/ + +*.pbxuser +*.mode1v3 +*.mode2v3 +*.perspectivev3 + +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + +xcuserdata + +*.moved-aside + +*.pyc +*sync/ +Icon? +.tags* + +/Flutter/Generated.xcconfig +/Flutter/ephemeral/ +/Flutter/flutter_export_environment.sh diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift new file mode 100644 index 000000000000..1fdfcdff529c --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift @@ -0,0 +1,36 @@ +#if os(iOS) +import Flutter +import UIKit +#elseif os(macOS) +import Cocoa +import FlutterMacOS +#endif + +public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { + public static func register(with registrar: FlutterPluginRegistrar) { + #if os(iOS) + let messenger = registrar.messenger() + #elseif os(macOS) + let messenger = registrar.messenger + #endif + + let channel = FlutterMethodChannel(name: "cross_file_darwin", binaryMessenger: messenger) + let instance = CrossFileDarwinPlugin() + registrar.addMethodCallDelegate(instance, channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "getPlatformVersion": + #if os(iOS) + result("iOS " + UIDevice.current.systemVersion) + #elseif os(macOS) + result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString) + #else + result(FlutterMethodNotImplemented) + #endif + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/Resources/PrivacyInfo.xcprivacy b/packages/cross_file/cross_file_darwin/darwin/Resources/PrivacyInfo.xcprivacy new file mode 100644 index 000000000000..a34b7e2e60cc --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Resources/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec new file mode 100644 index 000000000000..166ea7526ef1 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec @@ -0,0 +1,37 @@ +# +# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. +# Run `pod lib lint cross_file_darwin.podspec` to validate before publishing. +# +Pod::Spec.new do |s| + s.name = 'cross_file_darwin' + s.version = '0.0.1' + s.summary = 'A new Flutter plugin project.' + s.description = <<-DESC +A new Flutter plugin project. + DESC + s.homepage = 'http://example.com' + s.license = { :file => '../LICENSE' } + s.author = { 'Your Company' => 'email@example.com' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + + # Set the deployment targets for both iOS and macOS. + s.ios.deployment_target = '13.0' + s.osx.deployment_target = '10.15' + + # Define the platform-specific dependencies. + s.ios.dependency 'Flutter' + s.osx.dependency 'FlutterMacOS' + + # Flutter.framework does not contain a i386 slice, which is specific to iOS. + s.ios.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } + s.osx.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + + s.swift_version = '5.0' + + # If your plugin requires a privacy manifest, for example if it uses any + # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your + # plugin's privacy impact, and then uncomment this line. For more information, + # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files + # s.resource_bundles = {'cross_file_darwin_privacy' => ['Resources/PrivacyInfo.xcprivacy']} +end diff --git a/packages/cross_file/cross_file_darwin/example/.gitignore b/packages/cross_file/cross_file_darwin/example/.gitignore new file mode 100644 index 000000000000..3820a95c65c3 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/cross_file/cross_file_darwin/example/README.md b/packages/cross_file/cross_file_darwin/example/README.md new file mode 100644 index 000000000000..65ee88242c41 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/README.md @@ -0,0 +1,17 @@ +# cross_file_darwin_example + +Demonstrates how to use the cross_file_darwin plugin. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) +- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/packages/cross_file/cross_file_darwin/example/analysis_options.yaml b/packages/cross_file/cross_file_darwin/example/analysis_options.yaml new file mode 100644 index 000000000000..0d2902135cae --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart new file mode 100644 index 000000000000..7d792c675453 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart @@ -0,0 +1,24 @@ +// This is a basic Flutter integration test. +// +// Since integration tests run in a full Flutter application, they can interact +// with the host side of a plugin implementation, unlike Dart unit tests. +// +// For more information about Flutter integration tests, please see +// https://flutter.dev/to/integration-testing + +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +import 'package:cross_file_darwin/cross_file_darwin.dart'; + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + testWidgets('getPlatformVersion test', (WidgetTester tester) async { + final CrossFileDarwin plugin = CrossFileDarwin(); + final String? version = await plugin.getPlatformVersion(); + // The version string depends on the host platform running the test, so + // just assert that some non-empty string is returned. + expect(version?.isNotEmpty, true); + }); +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/.gitignore b/packages/cross_file/cross_file_darwin/example/ios/.gitignore new file mode 100644 index 000000000000..7a7f9873ad7d --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/AppFrameworkInfo.plist b/packages/cross_file/cross_file_darwin/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000000..391a902b2beb --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..592ceee85b89 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..592ceee85b89 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..d022f0831794 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,623 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..919434a6254f --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..e3773d42e24c --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/AppDelegate.swift b/packages/cross_file/cross_file_darwin/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000000..c30b367ec0a9 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,16 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..d36b1fab2d9d --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 zcmeHN2~<R zh`|8`A_PQ1nSu(UMFx?8j8PC!!VDphaL#`F42fd#7Vlc`zIE4n%Y~eiz4y1j|NDpi z?<@|pSJ-HM`qifhf@m%MamgwK83`XpBA<+azdF#2QsT{X@z0A9Bq>~TVErigKH1~P zRX-!h-f0NJ4Mh++{D}J+K>~~rq}d%o%+4dogzXp7RxX4C>Km5XEI|PAFDmo;DFm6G zzjVoB`@qW98Yl0Kvc-9w09^PrsobmG*Eju^=3f?0o-t$U)TL1B3;sZ^!++3&bGZ!o-*6w?;oOhf z=A+Qb$scV5!RbG+&2S}BQ6YH!FKb0``VVX~T$dzzeSZ$&9=X$3)_7Z{SspSYJ!lGE z7yig_41zpQ)%5dr4ff0rh$@ky3-JLRk&DK)NEIHecf9c*?Z1bUB4%pZjQ7hD!A0r-@NF(^WKdr(LXj|=UE7?gBYGgGQV zidf2`ZT@pzXf7}!NH4q(0IMcxsUGDih(0{kRSez&z?CFA0RVXsVFw3^u=^KMtt95q z43q$b*6#uQDLoiCAF_{RFc{!H^moH_cmll#Fc^KXi{9GDl{>%+3qyfOE5;Zq|6#Hb zp^#1G+z^AXfRKaa9HK;%b3Ux~U@q?xg<2DXP%6k!3E)PA<#4$ui8eDy5|9hA5&{?v z(-;*1%(1~-NTQ`Is1_MGdQ{+i*ccd96ab$R$T3=% zw_KuNF@vI!A>>Y_2pl9L{9h1-C6H8<)J4gKI6{WzGBi<@u3P6hNsXG=bRq5c+z;Gc3VUCe;LIIFDmQAGy+=mRyF++u=drBWV8-^>0yE9N&*05XHZpPlE zxu@?8(ZNy7rm?|<+UNe0Vs6&o?l`Pt>P&WaL~M&#Eh%`rg@Mbb)J&@DA-wheQ>hRV z<(XhigZAT z>=M;URcdCaiO3d^?H<^EiEMDV+7HsTiOhoaMX%P65E<(5xMPJKxf!0u>U~uVqnPN7T!X!o@_gs3Ct1 zlZ_$5QXP4{Aj645wG_SNT&6m|O6~Tsl$q?nK*)(`{J4b=(yb^nOATtF1_aS978$x3 zx>Q@s4i3~IT*+l{@dx~Hst21fR*+5}S1@cf>&8*uLw-0^zK(+OpW?cS-YG1QBZ5q! zgTAgivzoF#`cSz&HL>Ti!!v#?36I1*l^mkrx7Y|K6L#n!-~5=d3;K<;Zqi|gpNUn_ z_^GaQDEQ*jfzh;`j&KXb66fWEk1K7vxQIMQ_#Wu_%3 z4Oeb7FJ`8I>Px;^S?)}2+4D_83gHEq>8qSQY0PVP?o)zAv3K~;R$fnwTmI-=ZLK`= zTm+0h*e+Yfr(IlH3i7gUclNH^!MU>id$Jw>O?2i0Cila#v|twub21@e{S2v}8Z13( zNDrTXZVgris|qYm<0NU(tAPouG!QF4ZNpZPkX~{tVf8xY690JqY1NVdiTtW+NqyRP zZ&;T0ikb8V{wxmFhlLTQ&?OP7 z;(z*<+?J2~z*6asSe7h`$8~Se(@t(#%?BGLVs$p``;CyvcT?7Y!{tIPva$LxCQ&4W z6v#F*);|RXvI%qnoOY&i4S*EL&h%hP3O zLsrFZhv&Hu5tF$Lx!8(hs&?!Kx5&L(fdu}UI5d*wn~A`nPUhG&Rv z2#ixiJdhSF-K2tpVL=)5UkXRuPAFrEW}7mW=uAmtVQ&pGE-&az6@#-(Te^n*lrH^m@X-ftVcwO_#7{WI)5v(?>uC9GG{lcGXYJ~Q8q zbMFl7;t+kV;|;KkBW2!P_o%Czhw&Q(nXlxK9ak&6r5t_KH8#1Mr-*0}2h8R9XNkr zto5-b7P_auqTJb(TJlmJ9xreA=6d=d)CVbYP-r4$hDn5|TIhB>SReMfh&OVLkMk-T zYf%$taLF0OqYF?V{+6Xkn>iX@TuqQ?&cN6UjC9YF&%q{Ut3zv{U2)~$>-3;Dp)*(? zg*$mu8^i=-e#acaj*T$pNowo{xiGEk$%DusaQiS!KjJH96XZ-hXv+jk%ard#fu=@Q z$AM)YWvE^{%tDfK%nD49=PI|wYu}lYVbB#a7wtN^Nml@CE@{Gv7+jo{_V?I*jkdLD zJE|jfdrmVbkfS>rN*+`#l%ZUi5_bMS<>=MBDNlpiSb_tAF|Zy`K7kcp@|d?yaTmB^ zo?(vg;B$vxS|SszusORgDg-*Uitzdi{dUV+glA~R8V(?`3GZIl^egW{a919!j#>f` znL1o_^-b`}xnU0+~KIFLQ)$Q6#ym%)(GYC`^XM*{g zv3AM5$+TtDRs%`2TyR^$(hqE7Y1b&`Jd6dS6B#hDVbJlUXcG3y*439D8MrK!2D~6gn>UD4Imctb z+IvAt0iaW73Iq$K?4}H`7wq6YkTMm`tcktXgK0lKPmh=>h+l}Y+pDtvHnG>uqBA)l zAH6BV4F}v$(o$8Gfo*PB>IuaY1*^*`OTx4|hM8jZ?B6HY;F6p4{`OcZZ(us-RVwDx zUzJrCQlp@mz1ZFiSZ*$yX3c_#h9J;yBE$2g%xjmGF4ca z&yL`nGVs!Zxsh^j6i%$a*I3ZD2SoNT`{D%mU=LKaEwbN(_J5%i-6Va?@*>=3(dQy` zOv%$_9lcy9+(t>qohkuU4r_P=R^6ME+wFu&LA9tw9RA?azGhjrVJKy&8=*qZT5Dr8g--d+S8zAyJ$1HlW3Olryt`yE zFIph~Z6oF&o64rw{>lgZISC6p^CBer9C5G6yq%?8tC+)7*d+ib^?fU!JRFxynRLEZ zj;?PwtS}Ao#9whV@KEmwQgM0TVP{hs>dg(1*DiMUOKHdQGIqa0`yZnHk9mtbPfoLx zo;^V6pKUJ!5#n`w2D&381#5#_t}AlTGEgDz$^;u;-vxDN?^#5!zN9ngytY@oTv!nc zp1Xn8uR$1Z;7vY`-<*?DfPHB;x|GUi_fI9@I9SVRv1)qETbNU_8{5U|(>Du84qP#7 z*l9Y$SgA&wGbj>R1YeT9vYjZuC@|{rajTL0f%N@>3$DFU=`lSPl=Iv;EjuGjBa$Gw zHD-;%YOE@<-!7-Mn`0WuO3oWuL6tB2cpPw~Nvuj|KM@))ixuDK`9;jGMe2d)7gHin zS<>k@!x;!TJEc#HdL#RF(`|4W+H88d4V%zlh(7#{q2d0OQX9*FW^`^_<3r$kabWAB z$9BONo5}*(%kx zOXi-yM_cmB3>inPpI~)duvZykJ@^^aWzQ=eQ&STUa}2uT@lV&WoRzkUoE`rR0)`=l zFT%f|LA9fCw>`enm$p7W^E@U7RNBtsh{_-7vVz3DtB*y#*~(L9+x9*wn8VjWw|Q~q zKFsj1Yl>;}%MG3=PY`$g$_mnyhuV&~O~u~)968$0b2!Jkd;2MtAP#ZDYw9hmK_+M$ zb3pxyYC&|CuAbtiG8HZjj?MZJBFbt`ryf+c1dXFuC z0*ZQhBzNBd*}s6K_G}(|Z_9NDV162#y%WSNe|FTDDhx)K!c(mMJh@h87@8(^YdK$&d*^WQe8Z53 z(|@MRJ$Lk-&ii74MPIs80WsOFZ(NX23oR-?As+*aq6b?~62@fSVmM-_*cb1RzZ)`5$agEiL`-E9s7{GM2?(KNPgK1(+c*|-FKoy}X(D_b#etO|YR z(BGZ)0Ntfv-7R4GHoXp?l5g#*={S1{u-QzxCGng*oWr~@X-5f~RA14b8~B+pLKvr4 zfgL|7I>jlak9>D4=(i(cqYf7#318!OSR=^`xxvI!bBlS??`xxWeg?+|>MxaIdH1U~#1tHu zB{QMR?EGRmQ_l4p6YXJ{o(hh-7Tdm>TAX380TZZZyVkqHNzjUn*_|cb?T? zt;d2s-?B#Mc>T-gvBmQZx(y_cfkXZO~{N zT6rP7SD6g~n9QJ)8F*8uHxTLCAZ{l1Y&?6v)BOJZ)=R-pY=Y=&1}jE7fQ>USS}xP#exo57uND0i*rEk@$;nLvRB@u~s^dwRf?G?_enN@$t* zbL%JO=rV(3Ju8#GqUpeE3l_Wu1lN9Y{D4uaUe`g>zlj$1ER$6S6@{m1!~V|bYkhZA z%CvrDRTkHuajMU8;&RZ&itnC~iYLW4DVkP<$}>#&(`UO>!n)Po;Mt(SY8Yb`AS9lt znbX^i?Oe9r_o=?})IHKHoQGKXsps_SE{hwrg?6dMI|^+$CeC&z@*LuF+P`7LfZ*yr+KN8B4{Nzv<`A(wyR@!|gw{zB6Ha ziwPAYh)oJ(nlqSknu(8g9N&1hu0$vFK$W#mp%>X~AU1ay+EKWcFdif{% z#4!4aoVVJ;ULmkQf!ke2}3hqxLK>eq|-d7Ly7-J9zMpT`?dxo6HdfJA|t)?qPEVBDv z{y_b?4^|YA4%WW0VZd8C(ZgQzRI5(I^)=Ub`Y#MHc@nv0w-DaJAqsbEHDWG8Ia6ju zo-iyr*sq((gEwCC&^TYBWt4_@|81?=B-?#P6NMff(*^re zYqvDuO`K@`mjm_Jd;mW_tP`3$cS?R$jR1ZN09$YO%_iBqh5ftzSpMQQtxKFU=FYmP zeY^jph+g<4>YO;U^O>-NFLn~-RqlHvnZl2yd2A{Yc1G@Ga$d+Q&(f^tnPf+Z7serIU};17+2DU_f4Z z@GaPFut27d?!YiD+QP@)T=77cR9~MK@bd~pY%X(h%L={{OIb8IQmf-!xmZkm8A0Ga zQSWONI17_ru5wpHg3jI@i9D+_Y|pCqVuHJNdHUauTD=R$JcD2K_liQisqG$(sm=k9;L* z!L?*4B~ql7uioSX$zWJ?;q-SWXRFhz2Jt4%fOHA=Bwf|RzhwqdXGr78y$J)LR7&3T zE1WWz*>GPWKZ0%|@%6=fyx)5rzUpI;bCj>3RKzNG_1w$fIFCZ&UR0(7S?g}`&Pg$M zf`SLsz8wK82Vyj7;RyKmY{a8G{2BHG%w!^T|Njr!h9TO2LaP^_f22Q1=l$QiU84ao zHe_#{S6;qrC6w~7{y(hs-?-j?lbOfgH^E=XcSgnwW*eEz{_Z<_xN#0001NP)t-s|Ns9~ z#rXRE|M&d=0au&!`~QyF`q}dRnBDt}*!qXo`c{v z{Djr|@Adh0(D_%#_&mM$D6{kE_x{oE{l@J5@%H*?%=t~i_`ufYOPkAEn!pfkr2$fs z652Tz0001XNklqeeKN4RM4i{jKqmiC$?+xN>3Apn^ z0QfuZLym_5b<*QdmkHjHlj811{If)dl(Z2K0A+ekGtrFJb?g|wt#k#pV-#A~bK=OT ts8>{%cPtyC${m|1#B1A6#u!Q;umknL1chzTM$P~L002ovPDHLkV1lTfnu!1a literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000000..0bedcf2fd467 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000000..89c2725b70f1 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000000..f2e259c7c939 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/Main.storyboard b/packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000000..f3c28516fb38 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Info.plist b/packages/cross_file/cross_file_darwin/example/ios/Runner/Info.plist new file mode 100644 index 000000000000..f8648d3c710c --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Info.plist @@ -0,0 +1,70 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Cross File Darwin + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + cross_file_darwin_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Runner-Bridging-Header.h b/packages/cross_file/cross_file_darwin/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000000..308a2a560b42 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/SceneDelegate.swift b/packages/cross_file/cross_file_darwin/example/ios/Runner/SceneDelegate.swift new file mode 100644 index 000000000000..b9ce8ea2b2ad --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner/SceneDelegate.swift @@ -0,0 +1,6 @@ +import Flutter +import UIKit + +class SceneDelegate: FlutterSceneDelegate { + +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..74d18bc464f9 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,27 @@ +import Flutter +import UIKit +import XCTest + + +@testable import cross_file_darwin + +// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. +// +// See https://developer.apple.com/documentation/xctest for more information about using XCTest. + +class RunnerTests: XCTestCase { + + func testGetPlatformVersion() { + let plugin = CrossFileDarwinPlugin() + + let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) + + let resultExpectation = expectation(description: "result block must be called.") + plugin.handle(call) { result in + XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) + resultExpectation.fulfill() + } + waitForExpectations(timeout: 1) + } + +} diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart new file mode 100644 index 000000000000..0f92505796bc --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -0,0 +1,59 @@ +import 'package:flutter/material.dart'; +import 'dart:async'; + +import 'package:flutter/services.dart'; +import 'package:cross_file_darwin/cross_file_darwin.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatefulWidget { + const MyApp({super.key}); + + @override + State createState() => _MyAppState(); +} + +class _MyAppState extends State { + String _platformVersion = 'Unknown'; + final _crossFileDarwinPlugin = CrossFileDarwin(); + + @override + void initState() { + super.initState(); + initPlatformState(); + } + + // Platform messages are asynchronous, so we initialize in an async method. + Future initPlatformState() async { + String platformVersion; + // Platform messages may fail, so we use a try/catch PlatformException. + // We also handle the message potentially returning null. + try { + platformVersion = + await _crossFileDarwinPlugin.getPlatformVersion() ?? 'Unknown platform version'; + } on PlatformException { + platformVersion = 'Failed to get platform version.'; + } + + // If the widget was removed from the tree while the asynchronous platform + // message was in flight, we want to discard the reply rather than calling + // setState to update our non-existent appearance. + if (!mounted) return; + + setState(() { + _platformVersion = platformVersion; + }); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar(title: const Text('Plugin example app')), + body: Center(child: Text('Running on: $_platformVersion\n')), + ), + ); + } +} diff --git a/packages/cross_file/cross_file_darwin/example/macos/.gitignore b/packages/cross_file/cross_file_darwin/example/macos/.gitignore new file mode 100644 index 000000000000..746adbb6b9e1 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000000..c2efd0b608ba --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000000..c2efd0b608ba --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..c7fc52d02cad --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross_file_darwin_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_darwin_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_darwin_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_darwin_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_darwin_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_darwin_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_darwin_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..af474038da98 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/AppDelegate.swift b/packages/cross_file/cross_file_darwin/example/macos/Runner/AppDelegate.swift new file mode 100644 index 000000000000..b3c176141221 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..a2ec33f19f11 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..82b6f9d9a33e198f5747104729e1fcef999772a5 GIT binary patch literal 102994 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..13b35eba55c6dabc3aac36f33d859266c18fa0d0 GIT binary patch literal 5680 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5fa40fb3d1e0710331a48de5d256da3f275d GIT binary patch literal 520 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uuz(rC1}QWNE&K#jR^;j87-Auq zoUlN^K{r-Q+XN;zI ze|?*NFmgt#V#GwrSWaz^2G&@SBmck6ZcIFMww~vE<1E?M2#KUn1CzsB6D2+0SuRV@ zV2kK5HvIGB{HX-hQzs0*AB%5$9RJ@a;)Ahq#p$GSP91^&hi#6sg*;a~dt}4AclK>h z_3MoPRQ{i;==;*1S-mY<(JFzhAxMI&<61&m$J0NDHdJ3tYx~j0%M-uN6Zl8~_0DOkGXc0001@sz3l12C6Xg{AT~( zm6w64BA|AX`Ve)YY-glyudNN>MAfkXz-T7`_`fEolM;0T0BA)(02-OaW z0*cW7Z~ec94o8&g0D$N>b!COu{=m}^%oXZ4?T8ZyPZuGGBPBA7pbQMoV5HYhiT?%! zcae~`(QAN4&}-=#2f5fkn!SWGWmSeCISBcS=1-U|MEoKq=k?_x3apK>9((R zuu$9X?^8?@(a{qMS%J8SJPq))v}Q-ZyDm6Gbie0m92=`YlwnQPQP1kGSm(N2UJ3P6 z^{p-u)SSCTW~c1rw;cM)-uL2{->wCn2{#%;AtCQ!m%AakVs1K#v@(*-6QavyY&v&*wO_rCJXJuq$c$7ZjsW+pJo-$L^@!7X04CvaOpPyfw|FKvu;e(&Iw>Tbg zL}#8e^?X%TReXTt>gsBByt0kSU20oQx*~P=4`&tcZ7N6t-6LiK{LxX*p6}9c<0Pu^ zLx1w_P4P2V>bX=`F%v$#{sUDdF|;rbI{p#ZW`00Bgh(eB(nOIhy8W9T>3aQ=k8Z9% zB+TusFABF~J?N~fAd}1Rme=@4+1=M{^P`~se7}e3;mY0!%#MJf!XSrUC{0uZqMAd7%q zQY#$A>q}noIB4g54Ue)x>ofVm3DKBbUmS4Z-bm7KdKsUixva)1*&z5rgAG2gxG+_x zqT-KNY4g7eM!?>==;uD9Y4iI(Hu$pl8!LrK_Zb}5nv(XKW{9R144E!cFf36p{i|8pRL~p`_^iNo z{mf7y`#hejw#^#7oKPlN_Td{psNpNnM?{7{R-ICBtYxk>?3}OTH_8WkfaTLw)ZRTfxjW+0>gMe zpKg~`Bc$Y>^VX;ks^J0oKhB#6Ukt{oQhN+o2FKGZx}~j`cQB%vVsMFnm~R_1Y&Ml? zwFfb~d|dW~UktY@?zkau>Owe zRroi(<)c4Ux&wJfY=3I=vg)uh;sL(IYY9r$WK1$F;jYqq1>xT{LCkIMb3t2jN8d`9 z=4(v-z7vHucc_fjkpS}mGC{ND+J-hc_0Ix4kT^~{-2n|;Jmn|Xf9wGudDk7bi*?^+ z7fku8z*mbkGm&xf&lmu#=b5mp{X(AwtLTf!N`7FmOmX=4xwbD=fEo8CaB1d1=$|)+ z+Dlf^GzGOdlqTO8EwO?8;r+b;gkaF^$;+#~2_YYVH!hD6r;PaWdm#V=BJ1gH9ZK_9 zrAiIC-)z)hRq6i5+$JVmR!m4P>3yJ%lH)O&wtCyum3A*})*fHODD2nq!1@M>t@Za+ zH6{(Vf>_7!I-APmpsGLYpl7jww@s5hHOj5LCQXh)YAp+y{gG(0UMm(Ur z3o3n36oFwCkn+H*GZ-c6$Y!5r3z*@z0`NrB2C^q#LkOuooUM8Oek2KBk}o1PU8&2L z4iNkb5CqJWs58aR394iCU^ImDqV;q_Pp?pl=RB2372(Io^GA^+oKguO1(x$0<7w3z z)j{vnqEB679Rz4i4t;8|&Zg77UrklxY9@GDq(ZphH6=sW`;@uIt5B?7Oi?A0-BL}(#1&R;>2aFdq+E{jsvpNHjLx2t{@g1}c~DQcPNmVmy| zNMO@ewD^+T!|!DCOf}s9dLJU}(KZy@Jc&2Nq3^;vHTs}Hgcp`cw&gd7#N}nAFe3cM1TF%vKbKSffd&~FG9y$gLyr{#to)nxz5cCASEzQ}gz8O)phtHuKOW6p z@EQF(R>j%~P63Wfosrz8p(F=D|Mff~chUGn(<=CQbSiZ{t!e zeDU-pPsLgtc#d`3PYr$i*AaT!zF#23htIG&?QfcUk+@k$LZI}v+js|yuGmE!PvAV3 ztzh90rK-0L6P}s?1QH`Ot@ilbgMBzWIs zIs6K<_NL$O4lwR%zH4oJ+}JJp-bL6~%k&p)NGDMNZX7)0kni&%^sH|T?A)`z z=adV?!qnWx^B$|LD3BaA(G=ePL1+}8iu^SnnD;VE1@VLHMVdSN9$d)R(Wk{JEOp(P zm3LtAL$b^*JsQ0W&eLaoYag~=fRRdI>#FaELCO7L>zXe6w*nxN$Iy*Q*ftHUX0+N- zU>{D_;RRVPbQ?U+$^%{lhOMKyE5>$?U1aEPist+r)b47_LehJGTu>TcgZe&J{ z{q&D{^Ps~z7|zj~rpoh2I_{gAYNoCIJmio3B}$!5vTF*h$Q*vFj~qbo%bJCCRy509 zHTdDh_HYH8Zb9`}D5;;J9fkWOQi%Y$B1!b9+ESj+B@dtAztlY2O3NE<6HFiqOF&p_ zW-K`KiY@RPSY-p9Q99}Hcd05DT79_pfb{BV7r~?9pWh=;mcKBLTen%THFPo2NN~Nf zriOtFnqx}rtO|A6k!r6 zf-z?y-UD{dT0kT9FJ`-oWuPHbo+3wBS(}?2ql(+e@VTExmfnB*liCb zmeI+v5*+W_L;&kQN^ChW{jE0Mw#0Tfs}`9bk3&7UjxP^Ke(%eJu2{VnW?tu7Iqecm zB5|=-QdzK$=h50~{X3*w4%o1FS_u(dG2s&427$lJ?6bkLet}yYXCy)u_Io1&g^c#( z-$yYmSpxz{>BL;~c+~sxJIe1$7eZI_9t`eB^Pr0)5CuA}w;;7#RvPq|H6!byRzIJG ziQ7a4y_vhj(AL`8PhIm9edCv|%TX#f50lt8+&V+D4<}IA@S@#f4xId80oH$!_!q?@ zFRGGg2mTv&@76P7aTI{)Hu%>3QS_d)pQ%g8BYi58K~m-Ov^7r8BhX7YC1D3vwz&N8{?H*_U7DI?CI)+et?q|eGu>42NJ?K4SY zD?kc>h@%4IqNYuQ8m10+8xr2HYg2qFNdJl=Tmp&ybF>1>pqVfa%SsV*BY$d6<@iJA ziyvKnZ(~F9xQNokBgMci#pnZ}Igh0@S~cYcU_2Jfuf|d3tuH?ZSSYBfM(Y3-JBsC|S9c;# zyIMkPxgrq};0T09pjj#X?W^TFCMf1-9P{)g88;NDI+S4DXe>7d3Mb~i-h&S|Jy{J< zq3736$bH?@{!amD!1Ys-X)9V=#Z={fzsjVYMX5BG6%}tkzwC#1nQLj1y1f#}8**4Y zAvDZHw8)N)8~oWC88CgzbwOrL9HFbk4}h85^ptuu7A+uc#$f^9`EWv1Vr{5+@~@Uv z#B<;-nt;)!k|fRIg;2DZ(A2M2aC65kOIov|?Mhi1Sl7YOU4c$T(DoRQIGY`ycfkn% zViHzL;E*A{`&L?GP06Foa38+QNGA zw3+Wqs(@q+H{XLJbwZzE(omw%9~LPZfYB|NF5%j%E5kr_xE0u;i?IOIchn~VjeDZ) zAqsqhP0vu2&Tbz3IgJvMpKbThC-@=nk)!|?MIPP>MggZg{cUcKsP8|N#cG5 zUXMXxcXBF9`p>09IR?x$Ry3;q@x*%}G#lnB1}r#!WL88I@uvm}X98cZ8KO&cqT1p> z+gT=IxPsq%n4GWgh-Bk8E4!~`r@t>DaQKsjDqYc&h$p~TCh8_Mck5UB84u6Jl@kUZCU9BA-S!*bf>ZotFX9?a_^y%)yH~rsAz0M5#^Di80_tgoKw(egN z`)#(MqAI&A84J#Z<|4`Co8`iY+Cv&iboMJ^f9ROUK0Lm$;-T*c;TCTED_0|qfhlcS zv;BD*$Zko#nWPL}2K8T-?4}p{u)4xon!v_(yVW8VMpxg4Kh^J6WM{IlD{s?%XRT8P|yCU`R&6gwB~ zg}{At!iWCzOH37!ytcPeC`(({ovP7M5Y@bYYMZ}P2Z3=Y_hT)4DRk}wfeIo%q*M9UvXYJq!-@Ly79m5aLD{hf@BzQB>FdQ4mw z6$@vzSKF^Gnzc9vbccii)==~9H#KW<6)Uy1wb~auBn6s`ct!ZEos`WK8e2%<00b%# zY9Nvnmj@V^K(a_38dw-S*;G-(i(ETuIwyirs?$FFW@|66a38k+a%GLmucL%Wc8qk3 z?h_4!?4Y-xt)ry)>J`SuY**fuq2>u+)VZ+_1Egzctb*xJ6+7q`K$^f~r|!i?(07CD zH!)C_uerf-AHNa?6Y61D_MjGu*|wcO+ZMOo4q2bWpvjEWK9yASk%)QhwZS%N2_F4& z16D18>e%Q1mZb`R;vW{+IUoKE`y3(7p zplg5cBB)dtf^SdLd4n60oWie|(ZjgZa6L*VKq02Aij+?Qfr#1z#fwh92aV-HGd^_w zsucG24j8b|pk>BO7k8dS86>f-jBP^Sa}SF{YNn=^NU9mLOdKcAstv&GV>r zLxKHPkFxpvE8^r@MSF6UA}cG`#yFL8;kA7ccH9D=BGBtW2;H>C`FjnF^P}(G{wU;G z!LXLCbPfsGeLCQ{Ep$^~)@?v`q(uI`CxBY44osPcq@(rR-633!qa zsyb>?v%@X+e|Mg`+kRL*(;X>^BNZz{_kw5+K;w?#pReiw7eU8_Z^hhJ&fj80XQkuU z39?-z)6Fy$I`bEiMheS(iB6uLmiMd1i)cbK*9iPpl+h4x9ch7x- z1h4H;W_G?|)i`z??KNJVwgfuAM=7&Apd3vm#AT8uzQZ!NII}}@!j)eIfn53h{NmN7 zAKG6SnKP%^k&R~m5#@_4B@V?hYyHkm>0SQ@PPiw*@Tp@UhP-?w@jW?nxXuCipMW=L zH*5l*d@+jXm0tIMP_ec6Jcy6$w(gKK@xBX8@%oPaSyG;13qkFb*LuVx3{AgIyy&n3 z@R2_DcEn|75_?-v5_o~%xEt~ONB>M~tpL!nOVBLPN&e5bn5>+7o0?Nm|EGJ5 zmUbF{u|Qn?cu5}n4@9}g(G1JxtzkKv(tqwm_?1`?YSVA2IS4WI+*(2D*wh&6MIEhw z+B+2U<&E&|YA=3>?^i6)@n1&&;WGHF-pqi_sN&^C9xoxME5UgorQ_hh1__zzR#zVC zOQt4q6>ME^iPJ37*(kg4^=EFqyKH@6HEHXy79oLj{vFqZGY?sVjk!BX^h$SFJlJnv z5uw~2jLpA)|0=tp>qG*tuLru?-u`khGG2)o{+iDx&nC}eWj3^zx|T`xn5SuR;Aw8U z`p&>dJw`F17@J8YAuW4=;leBE%qagVTG5SZdh&d)(#ZhowZ|cvWvGMMrfVsbg>_~! z19fRz8CSJdrD|Rl)w!uznBF&2-dg{>y4l+6(L(vzbLA0Bk&`=;oQQ>(M8G=3kto_) zP8HD*n4?MySO2YrG6fwSrVmnesW+D&fxjfEmp=tPd?RKLZJcH&K(-S+x)2~QZ$c(> zru?MND7_HPZJVF%wX(49H)+~!7*!I8w72v&{b={#l9yz+S_aVPc_So%iF8>$XD1q1 zFtucO=rBj0Ctmi0{njN8l@}!LX}@dwl>3yMxZ;7 z0Ff2oh8L)YuaAGOuZ5`-p%Z4H@H$;_XRJQ|&(MhO78E|nyFa158gAxG^SP(vGi^+< zChY}o(_=ci3Wta#|K6MVljNe0T$%Q5ylx-v`R)r8;3+VUpp-)7T`-Y&{Zk z*)1*2MW+_eOJtF5tCMDV`}jg-R(_IzeE9|MBKl;a7&(pCLz}5<Zf+)T7bgNUQ_!gZtMlw=8doE}#W+`Xp~1DlE=d5SPT?ymu!r4z%&#A-@x^=QfvDkfx5-jz+h zoZ1OK)2|}_+UI)i9%8sJ9X<7AA?g&_Wd7g#rttHZE;J*7!e5B^zdb%jBj&dUDg4&B zMMYrJ$Z%t!5z6=pMGuO-VF~2dwjoXY+kvR>`N7UYfIBMZGP|C7*O=tU z2Tg_xi#Q3S=1|=WRfZD;HT<1D?GMR%5kI^KWwGrC@P2@R>mDT^3qsmbBiJc21kip~ zZp<7;^w{R;JqZ)C4z-^wL=&dBYj9WJBh&rd^A^n@07qM$c+kGv^f+~mU5_*|eePF| z3wDo-qaoRjmIw<2DjMTG4$HP{z54_te_{W^gu8$r=q0JgowzgQPct2JNtWPUsjF8R zvit&V8$(;7a_m%%9TqPkCXYUp&k*MRcwr*24>hR! z$4c#E=PVE=P4MLTUBM z7#*RDe0}=B)(3cvNpOmWa*eH#2HR?NVqXdJ=hq);MGD07JIQQ7Y0#iD!$C+mk7x&B zMwkS@H%>|fmSu#+ zI!}Sb(%o29Vkp_Th>&&!k7O>Ba#Om~B_J{pT7BHHd8(Ede(l`7O#`_}19hr_?~JP9 z`q(`<)y>%)x;O7)#-wfCP{?llFMoH!)ZomgsOYFvZ1DxrlYhkWRw#E-#Qf*z@Y-EQ z1~?_=c@M4DO@8AzZ2hKvw8CgitzI9yFd&N1-{|vP#4IqYb*#S0e3hrjsEGlnc4xwk z4o!0rxpUt8j&`mJ8?+P8G{m^jbk)bo_UPM+ifW*y-A*et`#_Ja_3nYyRa9fAG1Xr5 z>#AM_@PY|*u)DGRWJihZvgEh#{*joJN28uN7;i5{kJ*Gb-TERfN{ERe_~$Es~NJCpdKLRvdj4658uYYx{ng7I<6j~w@p%F<7a(Ssib|j z51;=Py(Nu*#hnLx@w&8X%=jrADn3TW>kplnb zYbFIWWVQXN7%Cwn6KnR)kYePEBmvM45I)UJb$)ninpdYg3a5N6pm_7Q+9>!_^xy?k za8@tJ@OOs-pRAAfT>Nc2x=>sZUs2!9Dwa%TTmDggH4fq(x^MW>mcRyJINlAqK$YQCMgR8`>6=Sg$ zFnJZsA8xUBXIN3i70Q%8px@yQPMgVP=>xcPI38jNJK<=6hC={a07+n@R|$bnhB)X$ z(Zc%tadp70vBTnW{OUIjTMe38F}JIH$#A}PB&RosPyFZMD}q}5W%$rh>5#U;m`z2K zc(&WRxx7DQLM-+--^w*EWAIS%bi>h587qkwu|H=hma3T^bGD&Z!`u(RKLeNZ&pI=q$|HOcji(0P1QC!YkAp*u z3%S$kumxR}jU<@6`;*-9=5-&LYRA<~uFrwO3U0k*4|xUTp4ZY7;Zbjx|uw&BWU$zK(w55pWa~#=f$c zNDW0O68N!xCy>G}(CX=;8hJLxAKn@Aj(dbZxO8a$+L$jK8$N-h@4$i8)WqD_%Snh4 zR?{O%k}>lr>w$b$g=VP8mckcCrjnp>uQl5F_6dPM8FWRqs}h`DpfCv20uZhyY~tr8 zkAYW4#yM;*je)n=EAb(q@5BWD8b1_--m$Q-3wbh1hM{8ihq7UUQfg@)l06}y+#=$( z$x>oVYJ47zAC^>HLRE-!HitjUixP6!R98WU+h>zct7g4eD;Mj#FL*a!VW!v-@b(Jv zj@@xM5noCp5%Vk3vY{tyI#oyDV7<$`KG`tktVyC&0DqxA#>V;-3oH%NW|Q&=UQ&zU zXNIT67J4D%5R1k#bW0F}TD`hlW7b)-=-%X4;UxQ*u4bK$mTAp%y&-(?{sXF%e_VH6 zTkt(X)SSN|;8q@8XX6qfR;*$r#HbIrvOj*-5ND8RCrcw4u8D$LXm5zlj@E5<3S0R# z??=E$p{tOk96$SloZ~ARe5`J=dB|Nj?u|zy2r(-*(q^@YwZiTF@QzQyPx_l=IDKa) zqD@0?IHJqSqZ_5`)81?4^~`yiGh6>7?|dKa8!e|}5@&qV!Iu9<@G?E}Vx9EzomB3t zEbMEm$TKGwkHDpirp;FZD#6P5qIlQJ8}rf;lHoz#h4TFFPYmS3+8(13_Mx2`?^=8S z|0)0&dQLJTU6{b%*yrpQe#OKKCrL8}YKw+<#|m`SkgeoN69TzIBQOl_Yg)W*w?NW) z*WxhEp$zQBBazJSE6ygu@O^!@Fr46j=|K`Mmb~xbggw7<)BuC@cT@Bwb^k?o-A zKX^9AyqR?zBtW5UA#siILztgOp?r4qgC`9jYJG_fxlsVSugGprremg-W(K0{O!Nw-DN%=FYCyfYA3&p*K>+|Q}s4rx#CQK zNj^U;sLM#q8}#|PeC$p&jAjqMu(lkp-_50Y&n=qF9`a3`Pr9f;b`-~YZ+Bb0r~c+V z*JJ&|^T{}IHkwjNAaM^V*IQ;rk^hnnA@~?YL}7~^St}XfHf6OMMCd9!vhk#gRA*{L zp?&63axj|Si%^NW05#87zpU_>QpFNb+I00v@cHwvdBn+Un)n2Egdt~LcWOeBW4Okm zD$-e~RD+W|UB;KQ;a7GOU&%p*efGu2$@wR74+&iP8|6#_fmnh^WcJLs)rtz{46);F z4v0OL{ZP9550>2%FE(;SbM*#sqMl*UXOb>ch`fJ|(*bOZ9=EB1+V4fkQ)hjsm3-u^Pk-4ji_uDDHdD>84tER!MvbH`*tG zzvbhBR@}Yd`azQGavooV=<WbvWLlO#x`hyO34mKcxrGv=`{ssnP=0Be5#1B;Co9 zh{TR>tjW2Ny$ZxJpYeg57#0`GP#jxDCU0!H15nL@@G*HLQcRdcsUO3sO9xvtmUcc{F*>FQZcZ5bgwaS^k-j5mmt zI7Z{Xnoml|A(&_{imAjK!kf5>g(oDqDI4C{;Bv162k8sFNr;!qPa2LPh>=1n z=^_9)TsLDvTqK7&*Vfm5k;VXjBW^qN3Tl&}K=X5)oXJs$z3gk0_+7`mJvz{pK|FVs zHw!k&7xVjvY;|(Py<;J{)b#Yjj*LZO7x|~pO4^MJ2LqK3X;Irb%nf}L|gck zE#55_BNsy6m+W{e zo!P59DDo*s@VIi+S|v93PwY6d?CE=S&!JLXwE9{i)DMO*_X90;n2*mPDrL%{iqN!?%-_95J^L z=l<*{em(6|h7DR4+4G3Wr;4*}yrBkbe3}=p7sOW1xj!EZVKSMSd;QPw>uhKK z#>MlS@RB@-`ULv|#zI5GytO{=zp*R__uK~R6&p$q{Y{iNkg61yAgB8C^oy&``{~FK z8hE}H&nIihSozKrOONe5Hu?0Zy04U#0$fB7C6y~?8{or}KNvP)an=QP&W80mj&8WL zEZQF&*FhoMMG6tOjeiCIV;T{I>jhi9hiUwz?bkX3NS-k5eWKy)Mo_orMEg4sV6R6X&i-Q%JG;Esl+kLpn@Bsls9O|i9z`tKB^~1D5)RIBB&J<6T@a4$pUvh$IR$%ubH)joi z!7>ON0DPwx=>0DA>Bb^c?L8N0BBrMl#oDB+GOXJh;Y&6I)#GRy$W5xK%a;KS8BrER zX)M>Rdoc*bqP*L9DDA3lF%U8Yzb6RyIsW@}IKq^i7v&{LeIc=*ZHIbO68x=d=+0T( zev=DT9f|x!IWZNTB#N7}V4;9#V$%Wo0%g>*!MdLOEU>My0^gni9ocID{$g9ytD!gy zKRWT`DVN(lcYjR|(}f0?zgBa3SwunLfAhx><%u0uFkrdyqlh8_g zDKt#R6rA2(Vm2LW_>3lBNYKG_F{TEnnKWGGC15y&OebIRhFL4TeMR*v9i0wPoK#H< zu4){s4K&K)K(9~jgGm;H7lS7y_RYfS;&!Oj5*eqbvEcW^a*i67nevzOZxN6F+K~A%TYEtsAVsR z@J=1hc#Dgs7J2^FL|qV&#WBFQyDtEQ2kPO7m2`)WFhqAob)Y>@{crkil6w9VoA?M6 zADGq*#-hyEVhDG5MQj677XmcWY1_-UO40QEP&+D)rZoYv^1B_^w7zAvWGw&pQyCyx zD|ga$w!ODOxxGf_Qq%V9Z7Q2pFiUOIK818AGeZ-~*R zI1O|SSc=3Z?#61Rd|AXx2)K|F@Z1@x!hBBMhAqiU)J=U|Y)T$h3D?ZPPQgkSosnN! zIqw-t$0fqsOlgw3TlHJF*t$Q@bg$9}A3X=cS@-yU3_vNG_!#9}7=q7!LZ?-%U26W4 z$d>_}*s1>Ac%3uFR;tnl*fNlylJ)}r2^Q3&@+is3BIv<}x>-^_ng;jhdaM}6Sg3?p z0jS|b%QyScy3OQ(V*~l~bK>VC{9@FMuW_JUZO?y(V?LKWD6(MXzh}M3r3{7b4eB(#`(q1m{>Be%_<9jw8HO!x#yF6vez$c#kR+}s zZO-_;25Sxngd(}){zv?ccbLqRAlo;yog>4LH&uZUK1n>x?u49C)Y&2evH5Zgt~666 z_2_z|H5AO5Iqxv_Bn~*y1qzRPcob<+Otod5Xd2&z=C;u+F}zBB@b^UdGdUz|s!H}M zXG%KiLzn3G?FZgdY&3pV$nSeY?ZbU^jhLz9!t0K?ep}EFNqR1@E!f*n>x*!uO*~JF zW9UXWrVgbX1n#76_;&0S7z}(5n-bqnII}_iDsNqfmye@)kRk`w~1 z6j4h4BxcPe6}v)xGm%=z2#tB#^KwbgMTl2I*$9eY|EWAHFc3tO48Xo5rW z5oHD!G4kb?MdrOHV=A+8ThlIqL8Uu+7{G@ zb)cGBm|S^Eh5= z^E^SZ=yeC;6nNCdztw&TdnIz}^Of@Ke*@vjt)0g>Y!4AJvWiL~e7+9#Ibhe)> ziNwh>gWZL@FlWc)wzihocz+%+@*euwXhW%Hb>l7tf8aJe5_ZSH1w-uG|B;9qpcBP0 zM`r1Hu#htOl)4Cl1c7oY^t0e4Jh$-I(}M5kzWqh{F=g&IM#JiC`NDSd@BCKX#y<P@Gwl$3a3w z6<(b|K(X5FIR22M)sy$4jY*F4tT{?wZRI+KkZFb<@j@_C316lu1hq2hA|1wCmR+S@ zRN)YNNE{}i_H`_h&VUT5=Y(lN%m?%QX;6$*1P}K-PcPx>*S55v)qZ@r&Vcic-sjkm z! z=nfW&X`}iAqa_H$H%z3Tyz5&P3%+;93_0b;zxLs)t#B|up}JyV$W4~`8E@+BHQ+!y zuIo-jW!~)MN$2eHwyx-{fyGjAWJ(l8TZtUp?wZWBZ%}krT{f*^fqUh+ywHifw)_F> zp76_kj_B&zFmv$FsPm|L7%x-j!WP>_P6dHnUTv!9ZWrrmAUteBa`rT7$2ixO;ga8U z3!91micm}{!Btk+I%pMgcKs?H4`i+=w0@Ws-CS&n^=2hFTQ#QeOmSz6ttIkzmh^`A zYPq)G1l3h(E$mkyr{mvz*MP`x+PULBn%CDhltKkNo6Uqg!vJ#DA@BIYr9TQ`18Un2 zv$}BYzOQuay9}w(?JV63F$H6WmlYPPpH=R|CPb%C@BCv|&Q|&IcW7*LX?Q%epS z`=CPx{1HnJ9_46^=0VmNb>8JvMw-@&+V8SDLRYsa>hZXEeRbtf5eJ>0@Ds47zIY{N z42EOP9J8G@MXXdeiPx#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$?lu1NER9Fe^SItioK@|V(ZWmgL zZT;XwPgVuWM>O%^|Dc$VK;n&?9!&g5)aVsG8cjs5UbtxVVnQNOV~7Mrg3+jnU;rhE z6fhW6P)R>_eXrXo-RW*y6RQ_qcb^s1wTu$TwriZ`=JUws>vRi}5x}MW1MR#7p|gIWJlaLK;~xaN}b< z<-@=RX-%1mt`^O0o^~2=CD7pJ<<$Rp-oUL-7PuG>do^5W_Mk#unlP}6I@6NPxY`Q} zuXJF}!0l)vwPNAW;@5DjPRj?*rZxl zwn;A(cFV!xe^CUu+6SrN?xe#mz?&%N9QHf~=KyK%DoB8HKC)=w=3E?1Bqj9RMJs3U z5am3Uv`@+{jgqO^f}Lx_Jp~CoP3N4AMZr~4&d)T`R?`(M{W5WWJV^z~2B|-oih@h^ zD#DuzGbl(P5>()u*YGo*Och=oRr~3P1wOlKqI)udc$|)(bacG5>~p(y>?{JD7nQf_ z*`T^YL06-O>T(s$bi5v~_fWMfnE7Vn%2*tqV|?~m;wSJEVGkNMD>+xCu#um(7}0so zSEu7?_=Q64Q5D+fz~T=Rr=G_!L*P|(-iOK*@X8r{-?oBlnxMNNgCVCN9Y~ocu+?XA zjjovJ9F1W$Nf!{AEv%W~8oahwM}4Ruc+SLs>_I_*uBxdcn1gQ^2F8a*vGjgAXYyh? zWCE@c5R=tbD(F4nL9NS?$PN1V_2*WR?gjv3)4MQeizuH`;sqrhgykEzj z593&TGlm3h`sIXy_U<7(dpRXGgp0TB{>s?}D{fwLe>IV~exweOfH!qM@CV5kib!YA z6O0gvJi_0J8IdEvyP#;PtqP*=;$iI2t(xG2YI-e!)~kaUn~b{6(&n zp)?iJ`z2)Xh%sCV@BkU`XL%_|FnCA?cVv@h*-FOZhY5erbGh)%Q!Av#fJM3Csc_g zC2I6x%$)80`Tkz#KRA!h1FzY`?0es3t!rKDT5EjPe6B=BLPr7s0GW!if;Ip^!AmGW zL;$`Vdre+|FA!I4r6)keFvAx3M#1`}ijBHDzy)3t0gwjl|qC2YB`SSxFKHr(oY#H$)x{L$LL zBdLKTlsOrmb>T0wd=&6l3+_Te>1!j0OU8%b%N342^opKmT)gni(wV($s(>V-fUv@0p8!f`=>PxC|9=nu ze{ToBBj8b<{PLfXV$h8YPgA~E!_sF9bl;QOF{o6t&JdsX?}rW!_&d`#wlB6T_h;Xf zl{4Tz5>qjF4kZgjO7ZiLPRz_~U@k5%?=30+nxEh9?s78gZ07YHB`FV`4%hlQlMJe@J`+e(qzy+h(9yY^ckv_* zb_E6o4p)ZaWfraIoB2)U7_@l(J0O%jm+Or>8}zSSTkM$ASG^w3F|I? z$+eHt7T~04(_WfKh27zqS$6* zzyy-ZyqvSIZ0!kkSvHknm_P*{5TKLQs8S6M=ONuKAUJWtpxbL#2(_huvY(v~Y%%#~ zYgsq$JbLLprKkV)32`liIT$KKEqs$iYxjFlHiRNvBhxbDg*3@Qefw4UM$>i${R5uB zhvTgmqQsKA{vrKN;TSJU2$f9q=y{$oH{<)woSeV>fkIz6D8@KB zf4M%v%f5U2?<8B(xn}xV+gWP?t&oiapJhJbfa;agtz-YM7=hrSuxl8lAc3GgFna#7 zNjX7;`d?oD`#AK+fQ=ZXqfIZFEk{ApzjJF0=yO~Yj{7oQfXl+6v!wNnoqwEvrs81a zGC?yXeSD2NV!ejp{LdZGEtd1TJ)3g{P6j#2jLR`cpo;YX}~_gU&Gd<+~SUJVh+$7S%`zLy^QqndN<_9 zrLwnXrLvW+ew9zX2)5qw7)zIYawgMrh`{_|(nx%u-ur1B7YcLp&WFa24gAuw~& zKJD3~^`Vp_SR$WGGBaMnttT)#fCc^+P$@UHIyBu+TRJWbcw4`CYL@SVGh!X&y%!x~ zaO*m-bTadEcEL6V6*{>irB8qT5Tqd54TC4`h`PVcd^AM6^Qf=GS->x%N70SY-u?qr>o2*OV7LQ=j)pQGv%4~z zz?X;qv*l$QSNjOuQZ>&WZs2^@G^Qas`T8iM{b19dS>DaXX~=jd4B2u`P;B}JjRBi# z_a@&Z5ev1-VphmKlZEZZd2-Lsw!+1S60YwW6@>+NQ=E5PZ+OUEXjgUaXL-E0fo(E* zsjQ{s>n33o#VZm0e%H{`KJi@2ghl8g>a~`?mFjw+$zlt|VJhSU@Y%0TWs>cnD&61fW4e0vFSaXZa4-c}U{4QR8U z;GV3^@(?Dk5uc@RT|+5C8-24->1snH6-?(nwXSnPcLn#X_}y3XS)MI_?zQ$ZAuyg+ z-pjqsw}|hg{$~f0FzmmbZzFC0He_*Vx|_uLc!Ffeb8#+@m#Z^AYcWcZF(^Os8&Z4g zG)y{$_pgrv#=_rV^D|Y<_b@ICleUv>c<0HzJDOsgJb#Rd-Vt@+EBDPyq7dUM9O{Yp zuGUrO?ma2wpuJuwl1M=*+tb|qx7Doj?!F-3Z>Dq_ihFP=d@_JO;vF{iu-6MWYn#=2 zRX6W=`Q`q-+q@Db|6_a1#8B|#%hskH82lS|9`im0UOJn?N#S;Y0$%xZw3*jR(1h5s z?-7D1tnIafviko>q6$UyqVDq1o@cwyCb*})l~x<@s$5D6N=-Uo1yc49p)xMzxwnuZ zHt!(hu-Ek;Fv4MyNTgbW%rPF*dB=;@r3YnrlFV{#-*gKS_qA(G-~TAlZ@Ti~Yxw;k za1EYyX_Up|`rpbZ0&Iv#$;eC|c0r4XGaQ-1mw@M_4p3vKIIpKs49a8Ns#ni)G314Z z8$Ei?AhiT5dQGWUYdCS|IC7r z=-8ol>V?u!n%F*J^^PZ(ONT&$Ph;r6X;pj|03HlDY6r~0g~X#zuzVU%a&!fs_f|m?qYvg^Z{y?9Qh7Rn?T*F%7lUtA6U&={HzhYEzA`knx1VH> z{tqv?p@I(&ObD5L4|YJV$QM>Nh-X3cx{I&!$FoPC_2iIEJfPk-$;4wz>adRu@n`_y z_R6aN|MDHdK;+IJmyw(hMoDCFCQ(6?hCAG5&7p{y->0Uckv# zvooVuu04$+pqof777ftk<#42@KQ((5DPcSMQyzGOJ{e9H$a9<2Qi_oHjl{#=FUL9d z+~0^2`tcvmp0hENwfHR`Ce|<1S@p;MNGInXCtHnrDPXCKmMTZQ{HVm_cZ>@?Wa6}O zHsJc7wE)mc@1OR2DWY%ZIPK1J2p6XDO$ar`$RXkbW}=@rFZ(t85AS>>U0!yt9f49^ zA9@pc0P#k;>+o5bJfx0t)Lq#v4`OcQn~av__dZ-RYOYu}F#pdsl31C^+Qgro}$q~5A<*c|kypzd} ziYGZ~?}5o`S5lw^B{O@laad9M_DuJle- z*9C7o=CJh#QL=V^sFlJ0c?BaB#4bV^T(DS6&Ne&DBM_3E$S^S13qC$7_Z?GYXTpR@wqr70wu$7+qvf-SEUa5mdHvFbu^7ew!Z1a^ zo}xKOuT*gtGws-a{Tx}{#(>G~Y_h&5P@Q8&p!{*s37^QX_Ibx<6XU*AtDOIvk|^{~ zPlS}&DM5$Ffyu-T&0|KS;Wnaqw{9DB&B3}vcO14wn;)O_e@2*9B&0I_ zZz{}CMxx`hv-XouY>^$Y@J(_INeM>lIQI@I>dBAqq1)}?Xmx(qRuX^i4IV%=MF306 z9g)i*79pP%_7Ex?m6ag-4Tlm=Z;?DQDyC-NpUIb#_^~V_tsL<~5<&;Gf2N+p?(msn zzUD~g>OoW@O}y0@Z;RN)wjam`CipmT&O7a|YljZqU=U86 zedayEdY)2F#BJ6xvmW8K&ffdS*0!%N<%RB!2~PAT4AD*$W7yzHbX#Eja9%3aD+Ah2 zf#T;XJW-GMxpE=d4Y>}jE=#U`IqgSoWcuvgaWQ9j1CKzG zDkoMDDT)B;Byl3R2PtC`ip=yGybfzmVNEx{xi_1|Cbqj>=FxQc{g`xj6fIfy`D8fA z##!-H_e6o0>6Su&$H2kQTujtbtyNFeKc}2=|4IfLTnye#@$Au7Kv4)dnA;-fz@D_8 z)>irG$)dkBY~zX zC!ZXLy*L3xr6cb70QqfN#Q>lFIc<>}>la4@3%7#>a1$PU&O^&VszpxLC%*!m-cO{B z-Y}rQr4$84(hvy#R69H{H zJ*O#uJh)TF6fbXy;fZkk%X=CjsTK}o5N1a`d7kgYYZLPxsHx%9*_XN8VWXEkVJZ%A z1A+5(B;0^{T4aPYr8%i@i32h)_)|q?9vws)r+=5u)1YNftF5mknwfd*%jXA2TeP}Z zQ!m?xJ3?9LpPM?_A3$hQ1QxNbR&}^m z!F999s?p^ak#C4NM_x2p9FoXWJ$>r?lJ)2bG)sX{gExgLA2s5RwHV!h6!C~d_H||J z>9{E{mEv{Z1z~65Vix@dqM4ZqiU|!)eWX$mwS5mLSufxbpBqqS!jShq1bmwCR6 z4uBri7ezMeS6ycaXPVu(i2up$L; zjpMtB`k~WaNrdgM_R=e#SN?Oa*u%nQy01?()h4A(jyfeNfx;5o+kX?maO4#1A^L}0 zYNyIh@QVXIFiS0*tE}2SWTrWNP3pH}1Vz1;E{@JbbgDFM-_Mky^7gH}LEhl~Ve5PexgbIyZ(IN%PqcaV@*_`ZFb=`EjspSz%5m2E34BVT)d=LGyHVz@-e%9Ova*{5@RD;7=Ebkc2GP%pIP^P7KzKapnh`UpH?@h z$RBpD*{b?vhohOKf-JG3?A|AX|2pQ?(>dwIbWhZ38GbTm4AImRNdv_&<99ySX;kJ| zo|5YgbHZC#HYgjBZrvGAT4NZYbp}qkVSa;C-LGsR26Co+i_HM&{awuO9l)Ml{G8zD zs$M8R`r+>PT#Rg!J(K6T4xHq7+tscU(}N$HY;Yz*cUObX7J7h0#u)S7b~t^Oj}TBF zuzsugnst;F#^1jm>22*AC$heublWtaQyM6RuaquFd8V#hJ60Z3j7@bAs&?dD#*>H0SJaDwp%U~27>zdtn+ z|8sZzklZy$%S|+^ie&P6++>zbrq&?+{Yy11Y>@_ce@vU4ZulS@6yziG6;iu3Iu`M= zf3rcWG<+3F`K|*(`0mE<$89F@jSq;j=W#E>(R}2drCB7D*0-|D;S;(;TwzIJkGs|q z2qH{m_zZ+el`b;Bv-#bQ>}*VPYC|7`rgBFf2oivXS^>v<&HHTypvd4|-zn|=h=TG{ z05TH2+{T%EnADO>3i|CB zCu60#qk`}GW{n4l-E$VrqgZGbI zbQW690KgZt4U3F^5@bdO1!xu~p@7Y~*_FfWg2CdvED5P5#w#V46LH`<&V0{t&Ml~4 zHNi7lIa+#i+^Z6EnxO7KJQw)wD)4~&S-Ki8)3=jpqxmx6c&zU&<&h%*c$I(5{1HZT zc9WE}ijcWJiVa^Q^xC|WX0habl89qycOyeViIbi(LFsEY_8a|+X^+%Qv+W4vzj>`y zpuRnjc-eHNkvXvI_f{=*FX=OKQzT?bck#2*qoKTHmDe>CDb&3AngA1O)1b}QJ1Tun z_<@yVEM>qG7664Pa@dzL@;DEh`#?yM+M|_fQS<7yv|i*pw)|Z8)9IR+QB7N3v3K(wv4OY*TXnH&X0nQB}?|h2XQeGL^q~N7N zDFa@x0E(UyN7k9g%IFq7Sf+EAfE#K%%#`)!90_)Dmy3Bll&e1vHQyPA87TaF(xbqMpDntVp?;8*$87STop$!EAnGhZ?>mqPJ(X zFsr336p3P{PpZCGn&^LP(JjnBbl_3P3Kcq+m}xVFMVr1zdCPJMDIV_ki#c=vvTwbU z*gKtfic&{<5ozL6Vfpx>o2Tts?3fkhWnJD&^$&+Mh5WGGyO7fG@6WDE`tEe(8<;+q z@Ld~g08XDzF8xtmpIj`#q^(Ty{Hq>t*v`pedHnuj(0%L(%sjkwp%s}wMd!a<*L~9T z9MM@s)Km~ogxlqEhIw5(lc46gCPsSosUFsgGDr8H{mj%OzJz{N#;bQ;KkV+ZWA1(9 zu0PXzyh+C<4OBYQ0v3z~Lr;=C@qmt8===Ov2lJ1=DeLfq*#jgT{YQCuwz?j{&3o_6 zsqp2Z_q-YWJg?C6=!Or|b@(zxTlg$ng2eUQzuC<+o)k<6^9ju_Z*#x+oioZ5T8Z_L zz9^A1h2eFS0O5muq8;LuDKwOv4A9pxmOjgb6L*i!-(0`Ie^d5Fsgspon%X|7 zC{RRXEmYn!5zP9XjG*{pLa)!2;PJB2<-tH@R7+E1cRo=Wz_5Ko8h8bB$QU%t9#vol zAoq?C$~~AsYC|AQQ)>>7BJ@{Cal)ZpqE=gjT+Juf!RD-;U0mbV1ED5PbvFD6M=qj1 zZ{QERT5@(&LQ~1X9xSf&@%r|3`S#ZCE=sWD`D4YQZ`MR`G&s>lN{y2+HqCfvgcw3E z-}Kp(dfGG?V|97kAHQX+OcKCZS`Q%}HD6u*e$~Ki&Vx53&FC!x94xJd4F2l^qQeFO z?&JdmgrdVjroKNJx64C!H&Vncr^w zzR#XI}Dn&o8jB~_YlVM^+#0W(G1LZH5K^|uYT@KSR z^Y5>^*Bc45E1({~EJB(t@4n9gb-eT#s@@7)J^^<_VV`Pm!h7av8XH6^5zO zOcQBhTGr;|MbRsgxCW69w{bl4EW#A~);L?d4*y#j8Ne=Z@fmJP0k4{_cQ~KA|Y#_#BuUiYx8y*za3_6Y}c=GSe7(2|KAfhdzud!Zq&}j)=o4 z7R|&&oX7~e@~HmyOOsCCwy`AR+deNjZ3bf6ijI_*tKP*_5JP3;0d;L_p(c>W1b%sG zJ*$wcO$ng^aW0E(5ldckV9unU7}OB7s?Wx(761?1^&8tA5y0_(ieV>(x-e@}1`lWC z-YH~G$D>#ud!SxK2_Iw{K%92=+{4yb-_XC>ji&j7)1ofp(OGa4jjF;Hd*`6YQL+Jf zffg+6CPc8F@EDPN{Kn96yip;?g@)qgkPo^nVKFqY?8!=h$G$V=<>%5J&iVjwR!7H0 z$@QL|_Q81I;Bnq8-5JyNRv$Y>`sWl{qhq>u+X|)@cMlsG!{*lu?*H`Tp|!uv z9oEPU1jUEj@ueBr}%Y)7Luyi)REaJV>eQ{+uy4uh0ep0){t;OU8D*RZ& zE-Z-&=BrWQLAD^A&qut&4{ZfhqK1ZQB0fACP)=zgx(0(o-`U62EzTkBkG@mXqbjXm z>w`HNeQM?Is&4xq@BB(K;wv5nI6EXas)XXAkUuf}5uSrZLYxRCQPefn-1^#OCd4aO zzF=dQ*CREEyWf@n6h7(uXLNgJIwGp#Xrsj6S<^bzQ7N0B0N{XlT;`=m9Olg<>KL}9 zlp>EKTx-h|%d1Ncqa=wnQEuE;sIO-f#%Bs?g4}&xS?$9MG?n$isHky0caj za8W+B^ERK#&h?(x)7LLpOqApV5F>sqB`sntV%SV>Q1;ax67qs+WcssfFeF3Xk=e4^ zjR2^(%K1oBq%0%Rf!y&WT;lu2Co(rHi|r1_uW)n{<7fGc-c=ft7Z0Q}r4W$o$@tQF#i?jDBwZ8h+=SC}3?anUp3mtRVv9l#H?-UD;HjTF zQ*>|}e=6gDrgI9p%c&4iMUkQa4zziS$bO&i#DI$Wu$7dz7-}XLk%!US^XUIFf2obO zFCTjVEtkvYSKWB;<0C;_B{HHs~ax_48^Cml*mjfBC5*7^HJZiLDir(3k&BerVIZF8zF;0q80eX8c zPN4tc+Dc5DqEAq$Y3B3R&XPZ=AQfFMXv#!RQnGecJONe0H;+!f^h5x0wS<+%;D}MpUbTNUBA}S2n&U59-_5HKr{L^jPsV8B^%NaH|tUr)mq=qCBv_- ziZ1xUp(ZzxUYTCF@C}To;u60?RIfTGS?#JnB8S8@j`TKPkAa)$My+6ziGaBcA@){d z91)%+v2_ba7gNecdj^8*I4#<11l!{XKl6s0zkXfJPxhP+@b+5ev{a>p*W-3*25c&} zmCf{g9mPWVQ$?Sp*4V|lT@~>RR)9iNdN^7KT@>*MU3&v^3e?=NTbG9!h6C|9zO097 zN{Qs6YwR-5$)~ z`b~qs`a1Dbx8P>%V=1XGjBptMf%P~sl1qbHVm1HYpY|-Z^Dar8^HqjIw}xaeRlsYa zJ_@Apy-??`gxPmb`m`0`z`#G7*_C}qiSZe~l2z65tE~IwMw$1|-u&t|z-8SxliH00 zlh1#kuqB56s+E&PWQ7Nz17?c}pN+A@-c^xLqh(j;mS|?>(Pf7(?qd z5q@jkc^nA&!K-}-1P=Ry0yyze0W!+h^iW}7jzC1{?|rEFFWbE^Yu7Y}t?jmP-D$f+ zmqFT7nTl0HL|4jwGm7w@a>9 zKD)V~+g~ysmei$OT5}%$&LK8?ib|8aY|>W3;P+0B;=oD=?1rg+PxKcP(d;OEzq1CKA&y#boc51P^ZJPPS)z5 zAZ)dd2$glGQXFj$`XBBJyl2y-aoBA8121JC9&~|_nY>nkmW>TLi%mWdn-^Jks-Jv| zSR*wij;A3Fcy8KsDjQ15?Z9oOj|Qw2;jgJiq>dxG(2I2RE- z$As!#zSFIskebqU2bnoM^N<4VWD2#>!;saPSsY8OaCCQqkCMdje$C?Sp%V}f2~tG5 z0whMYk6tcaABwu*x)ak@n4sMElGPX1_lmv@bgdI2jPdD|2-<~Jf`L`@>Lj7{<-uLQ zE3S_#3e10q-ra=vaDQ42QUY^@edh>tnTtpBiiDVUk5+Po@%RmuTntOlE29I4MeJI?;`7;{3e4Qst#i-RH6s;>e(Sc+ubF2_gwf5Qi%P!aa89fx6^{~A*&B4Q zKTF|Kx^NkiWx=RDhe<{PWXMQ;2)=SC=yZC&mh?T&CvFVz?5cW~ritRjG2?I0Av_cI z)=s!@MXpXbarYm>Kj0wOxl=eFMgSMc?62U#2gM^li@wKPK9^;;0_h7B>F>0>I3P`{ zr^ygPYp~WVm?Qbp6O3*O2)(`y)x>%ZXtztz zMAcwKDr=TCMY!S-MJ8|2MJCVNUBI0BkJV6?(!~W!_dC{TS=eh}t#X+2D>Kp&)ZN~q zvg!ogxUXu^y(P*;Q+y_rDoGeSCYxkaGPldDDx)k;ocJvvGO#1YKoQLHUf2h_pjm&1 zqh&!_KFH03FcJvSdfgUYMp=5EpigZ*8}7N_W%Ms^WSQ4hH`9>3061OEcxmf~TcYn5_oHtscWn zo5!ayj<_fZ)vHu3!A!7M;4y1QIr8YGy$P2qDD_4+T8^=^dB6uNsz|D>p~4pF3Nrb6 zcpRK*($<~JUqOya#M1=#IhOZ zG)W+rJS-x(6EoVz)P zsSo>JtnChdj9^);su%SkFG~_7JPM zEDz3gk2T7Y%x>1tWyia|op(ilEzvAujW?Xwlw>J6d7yEi8E zv30riR|a_MM%ZZX&n!qm0{2agq(s?x9E@=*tyT$nND+{Djpm7Rsy!+c$j+wqMwTOF zZL8BQ|I`<^bGW)5apO{lh(Asqen?_U`$_n0-Ob~Yd%^89oEe%9yGumQ_8Be+l2k+n zCxT%s?bMpv|AdWP7M1LQwLm|x+igA~;+iK-*+tClF&ueX_V}>=4gvZ01xpubQWXD_ zi?Un>&3=$fu)dgk-Z;0Ll}HK5_YM->l^Czrd0^cJ))(DwL2g3aZuza7ga9^|mT_70 z))}A}r1#-(9cxtn<9jGRwOB4hb9kK@YCgjfOM-90I$8@l=H^`K$cyhe2mTM|FY9vW znH~h)I<_aa#V1xmhk?Ng@$Jw-s%a!$BI4Us+Df+?J&gKAF-M`v}j`OWKP3>6`X`tEmhe#y*(Xm$_^Ybbs=%;L7h zp7q^C*qM}Krqsinq|WolR99>_!GL#Z71Hhz|IwQQv<>Ds09B?Je(lhI1(FInO8mc} zl$RyKCUmfku+Cd^8s0|t+e}5g7M{ZPJQH=UB3(~U&(w#Bz#@DTDHy>_UaS~AtN>4O zJ-I#U@R($fgupHebcpuEBX`SZ>kN!rW$#9>s{^3`86ZRQRtYTY)hiFm_9wU3c`SC8 z-5M%g)h}3Pt|wyj#F%}pGC@VL`9&>9P+_UbudCkS%y2w&*o})hBplrB*@Z?gel5q+ z%|*59(sR9GMk3xME}wd%&k?7~J)OL`rK#4d-haC7uaU8-L@?$K6(r<0e<;y83rK&` z3Q!1rD9WkcB8WBQ|WT|$u^lkr0UL4WH4EQTJyk@5gzHb18cOte4w zS`fLv8q;PvAZyY;*Go3Qw1~5#gP0D0ERla6M6#{; zr1l?bR}Nh+OC7)4bfAs(0ZD(axaw6j9v`^jh5>*Eo&$dAnt?c|Y*ckEORIiJXfGcM zEo`bmIq6rJm`XhkXR-^3d8^RTK2;nmVetHfUNugJG(4XLOu>HJA;0EWb~?&|0abr6 zxqVp@p=b3MN^|~?djPe!=eex(u!x>RYFAj|*T$cTi*Sd3Bme7Pri1tkK9N`KtRmXf zZYNBNtik97ct1R^vamQBfo9ZUR@k*LhIg8OR9d_{iv#t)LQV91^5}K5u{eyxwOFoU zHMVq$C>tfa@uNDW^_>EmO~WYQd(@!nKmAvSSIb&hPO|}g-3985t?|R&WZXvxS}Kt2i^eRe>WHb_;-K5cM4=@AN1>E&1c$k!w4O*oscx(f=<1K6l#8Exi)U(ZiZ zdr#YTP6?m1e1dOKysUjQ^>-MR={OuD00g6+(a^cvcmn#A_%Fh3Of%(qP5nvjS1=(> z|Ld8{u%(J}%2SY~+$4pjy{()5HN2MYUjg1X9umxOMFFPdM+IwOVEs4Z(olynvT%G) zt9|#VR}%O2@f6=+6uvbZv{3U)l;C{tuc zZ{K$rut=eS%3_~fQv^@$HV6#9)K9>|0qD$EV2$G^XUNBLM|5-ZmFF!KV)$4l^KVj@ zZ4fI}Knv*K%zPqK77}B-h_V{66VrmoZP2>@^euu8Rc}#qwRwt5uEBWcJJE5*5rT2t zA4Jpx`QQ~1Sh_n_a9x%Il!t1&B~J6p54zxAJx`REov${jeuL8h8x-z=?qwMAmPK5i z_*ES)BW(NZluu#Bmn1-NUKQip_X&_WzJy~J`WYxEJQ&Gu7DD< z&F9urE;}8S{x4{yB zaq~1Zrz%8)<`prSQv$eu5@1RY2WLu=waPTrn`WK%;G5(jt^FeM;gOdvXQjYhax~_> z{bS_`;t#$RYMu-;_Dd&o+LD<5Afg6v{NK?0d8dD5ohAN?QoocETBj?y{MB)jQ%UQ}#t3j&iL!qr@#6JEajR3@^k5wgLfI9S9dT2^f`2wd z%I#Q*@Ctk@w=(u)@QC}yBvUP&fFRR-uYKJ){Wp3&$s(o~W7OzgsUIPx0|ph2L1(r*_Pa@T@mcH^JxBjh09#fgo|W#gG7}|)k&uD1iZxb0 z@|Y)W79SKj9sS&EhmTD;uI#)FE6VwQ*YAr&foK$RI5H8_ripb$^=;U%gWbrrk4!5P zXDcyscEZoSH~n6VJu8$^6LE6)>+=o#Q-~*jmob^@191+Ot1w454e3)WMliLtY6~^w zW|n#R@~{5K#P+(w+XC%(+UcOrk|yzkEes=!qW%imu6>zjdb!B#`efaliKtN}_c!Jp zfyZa`n+Nx8;*AquvMT2;c8fnYszdDA*0(R`bsof1W<#O{v%O!1IO4WZe=>XBu_D%d zOwWDaEtX%@B>4V%f1+dKqcXT>m2!|&?}(GK8e&R=&w?V`*Vj)sCetWp9lr@@{xe6a zE)JL&;p}OnOO}Nw?vFyoccXT*z*?r}E8{uPtd;4<(hmX;d$rqJhEF}I+kD+m(ke;J z7Cm$W*CSdcD=RYEBhedg>tuT{PHqwCdDP*NkHv4rvQTXkzEn*Mb0oJz&+WfWIOS4@ zzpPJ|e%a-PIwOaOC7uQcHQ-q(SE(e@fj+7oC@34wzaBNaP;cw&gm{Z8yYX?V(lIv5 zKbg*zo1m5aGA4^lwJ|bAU=j3*d8S{vp!~fLFcK8s6%Ng55_qW_d*3R%e=34aDZPfD z&Le39j|ahp6E7B0*9OVdeMNrTErFatiE+=Z!XZ^tv0y%zZKXRTBuPyP&C{5(H?t)S zKV24_-TKpOmCPzU&by8R1Q5HY^@IDoeDA9MbgizgQ*F1Er~HVmvSU>vx}pZVQ&tr| zOtZl8vfY2#L<)gZ=ba&wG~EI*Vd?}lRMCf+!b5CDz$8~be-HKMo5omk$w7p4`Mym*IR8WiTz4^kKcUo^8Hkcsu14u z`Pkg`#-Y^A%CqJ0O@UF|caAulf68@(zhqp~YjzInh7qSN7Ov%Aj(Qz%{3zW|xubJ- ztNE_u_MO7Q_585r;xD?e=Er}@U1G@BKW5v$UM((eByhH2p!^g9W}99OD8VV@7d{#H zv)Eam+^K(5>-Ot~U!R$Um3prQmM)7DyK=iM%vy>BRX4#aH7*oCMmz07YB(EL!^%F7?CA#>zXqiYDhS;e?LYPTf(bte6B ztrfvDXYG*T;ExK-w?Knt{jNv)>KMk*sM^ngZ-WiUN;=0Ev^GIDMs=AyLg2V@3R z7ugNc45;4!RPxvzoT}3NCMeK$7j#q3r_xV(@t@OPRyoKBzHJ#IepkDsm$EJRxL)A* zf{_GQYttu^OXr$jHQn}zs$Eh|s|Z!r?Yi+bS-bi+PE*lH zo|6ztu6$r_?|B~S#m>imI!kQP9`6X426uHRri!wGcK;J;`%sFM(D#*Le~W*t2uH`Q z(HEO9-c_`mhA@4QhbW+tgtt9Pzx=_*3Kh~TB$SKmU4yx-Ay&)n%PZPKg#rD4H{%Ke zdMY@rf5EAFfqtrf?Vmk&N(_d-<=bvfOdPrYwY*;5%j@O6@O#Qj7LJTk-x3LN+dEKy+X z>~U8j3Ql`exr1jR>+S4nEy+4c2f{-Q!3_9)yY758tLGg7k^=nt<6h$YE$ltA+13S<}uOg#XHe6 zZHKdNsAnMQ_RIuB;mdoZ%RWpandzLR-BnjN2j@lkBbBd+?i ze*!5mC}!Qj(Q!rTu`KrRRqp22c=hF6<^v&iCDB`n7mHl;vdclcer%;{;=kA(PwdGG zdX#BWoC!leBC4);^J^tPkPbIe<)~nYb6R3u{HvC!NOQa?DC^Q`|_@ zcz;rk`a!4rSLAS>_=b@g?Yab4%=J3Cc7pRv8?_rHMl_aK*HSPU%0pG2Fyhef_biA!aW|-(( z*RIdG&Lmk(=(nk28Q1k1Oa$8Oa-phG%Mc6dT3>JIylcMMIc{&FsBYBD^n@#~>C?HG z*1&FpYVvXOU@~r2(BUa+KZv;tZ15#RewooEM0LFb>guQN;Z0EBFMFMZ=-m$a3;gVD z)2EBD4+*=6ZF?+)P`z@DOT;azK0Q4p4>NfwDR#Pd;no|{q_qB!zk1O8QojE;>zhPu z1Q=1z^0MYHo1*``H3ex|bW-Zy==5J4fE2;g6sq6YcXMYK5i|S^9(OSw#v!3^!EB<% zZF~J~CleS`V-peStyf*I%1^R88D;+8{{qN6-t!@gTARDg^w2`uSzFZbPQ!)q^oC}m zPo8VOQxq2BaIN`pAVFGu8!{p3}(+iZ`f4ck2ygVpEZMQW38nLpj3NQx+&sAkb8`}P3- zc>N*k6AG?r}bfO6_vccTuKX+*- z7W4Q#2``P0jIHYs)F>uG#AM#I6W2)!Nu2nD5{CRV_PmkDS2ditmbd#pggqEgAo%5oC?|CP zGa0CV)wA*ko!xC7pZYkqo{10CN_e00FX5SjWkI3?@XG}}bze!(&+k2$C-C`6temSk z_YyYpB^wh3woo`B zrMSTd4T?(X-jh`FeO76C(3xsOm9s2BP_b%ospg^!#*2*o9N;tf4(X9$qc_d(()yz5 zDk@1}u_Xd+86vy5RBs?LQCuYKCGPS;E4uFOi@V%1JTK&|eRf~lp$AV#;*#O}iRI2=i3rFL8{ zA^ptDZ0l6k-mq=hUJ0x$Y@J>UNfz~I5l63H(`~*v;qX`Z{zwsQQD-!wp0D&hyB8&Z z7$R07gIKGJ^%AvQ{4KM0edM39iFRx=P^6`!<1(s0t|JbB2tXs_B_IH9#ajH0C=-n+ z`nz`fKMBKLlf?2AC+|83M+0rqR%uhNGD;uKA6jOjp7YDe^4%0fRB<^bcjlS2KF~F; zu09wh1x0&4pG&76M;x8$u`b134t=dEPBn6PV|X29<#T4F1mxGF*HOgiWU8tN@cguI z_F@o+XL7FJztR63wC|j4x_DANzcX94r7Iz-O2x$({&qd*mdLG=-Rv)uZ}UlMR+F&q zU}=lkfb0p1>1Ho){o$@}mSKIV;h*$AND7~Dl)QzpFBlSM99Kx+F7GsVK5xcR? z_4Q(Z%cgk8ST}U;;=!LwyZVu^S$>B-Waeik%wzcKTIqeX=0FP(TGQ=nxi=dsS5BYF zl@?}NT!Y!Iyos^@v7XWXA{_bV~1lxz7gC?xuXxy0_?GaN!AhRRM5>)^t%&ODd;@HN5L{MD3 zc>i2keQZVm#?NrDwbfd}_<*5^U&w0zv~n-y8=GGN-!=_`FU^cM8oVCWRFxw?BM^YD zi=Vxz4q|jwPTg+?q7_XI)-S@gQkh>w0ZUB}a{^ z_i;`Y(~fvpI!vmW*A^|P7(6+@C4UeL2WATf{P1?H5rk`5{TL zcf!CgP6Mi{MvjZS)rfo7JLDZK7M7ANd$3`{j9baD*7{#Zu-33fOYUzjvtKzR2)_T1I1s7fe&z|=)QkX;=`zX8!Byw-veM#yr;|wjO^II>!B*B z0+w%;0(=*G3V@88t!}~zx)&do(uF=073Yeh*fEhZb3Vn>t!m(9p~Y_FdV3IgR)9eT z)~e9xpI%2deTWyHlXA(7srrfc_`7ACm!R>SoIgkuF8 z!wkOhrixFy9y@)GdxAntd!!7@=L_tFD2T5OdSUO)I%yj02le`qeQ=yKq$g^h)NG;# za(0J@#VBi^5YI|QI=rq{KlxwGabZJ0dKmfWDROkcM}lUN$@DV`K7fU?8CP2H23QPi zG?YF*=Vn=kTK*#Y_{AQN&oLju|0#E=fx%YVh>S{puu&K$b;BN*jIo@VYhqPiJPzzM>#kxoy0vW9i;ne2_BIG0zyRFp<3M(iY(%*M_>q0ulV2K}Tg zkG{EWKS{i%4DUuHi%DVKy%e+Q!~Uf`>>F6NgD{{I8~nO4!VgOvtFOc7(O)X`|7n*f zxBa4CJ-v9fUUH+`7sPVvpM_C*udZ@OTGTzx56QM5y~OlrZc&w9=)B?nmd@keRn+^= zvm~4sa5987LFDnU{(N|N zJAR8H@}p1fC+H(yTI4n#%~TbImMpuqYn9cQ<0QQ%=PzZItLkC*ef9WJUvfITKWh#D zc#__8`4am9%#NslIUw+<82#SR8AYG|woLfBg#!-&dqq}@P>|I0%lbdy0lSMmNe+}o zj0zZuFr6Wb?Y{Qy-S=|r`bdrDmhnmvkRnkdn`YCleU>Q$=je}LGhh>_QAj6aa_0Oc z%Swsmui;IRx7bN*=AAS@5yW&Y2hy;3&|HAiA8}!HT6!Z!RVn~MZg`RmI6&%#tBZDx zfD+y@Z~NWlk*4l13vmt3AK2wP!fQlnBbECL>?p)F?T)<`w&QN>cP_V>r7UTcsTaaP zTOb$f!P@zf$6>890NVKbIkG8rE?9!Y97sMSZjfF?A zYR8lp`LMoz~O?iaZN;gcX;LC-%Ia*R%A&SLx!YIf29?P+=XAAojK8!^OU*@?R&DK!#G_lsn!#;S375uZ&B0HH1|BO0R90$U>qs zSvHv>H~mAgNCcjo-e+;RjY6B9NCbQrZ|BHjTkehaU<9CSkdd>Vl*ifA2LNOP&R2Qdy3k3-TQ+ zbq=#vI43x`s=%~cGyN&y4Y!FxhwgDe@i6uv8^BLL&3z*SO=D0aLjih?gY4-9uWp5or)H+v~w6n5X#F-I52z=Z_p4JB(;M| zeaVFhuR2|3UD2MzVc~^nSoD2(dD#uL_1PdnIxeA{V5n`#3xf1Zx@4lw(DsQ&H$h zw#%3O<1173hjg2_nhKi!d1ej=h7y`hVjCNB6|HTnx>SWuCE-kgTnfT+YGX4_Lun({ zDv2`>d3vrS)tTf7ps_vvh!Cx^e1BFuWnEAh0(7fkNk|-3oU|iRWdsC6U)?Raft~HN z;^$U}vZK5O8|LV$>6X5T(uYkblv{zwPxnQBh(BQ5tA~J!vGiAMYP^_ki~pkIxDfOZ zUJDwq%O~WueeV6%uN<54&u*c&E4y431cklBNrb06zGOOy4XNT~JS-q(s6@)F@ovbe ze`fial(O4(-su%6@@1+V0MsdLLMyE8;)nou(7}czU(5ASaZYDT(kUZ0L(&g$nF^n9 z9-Pi`ZZLX&)^*M6As4_2Mmc9S7OT)F8KkL2NJ)KJcnCuWU=Wy402A&45#Q9Id~BBH z0cY*xlv!uXzKrXLH!xQu(OtJvEj|0-DmRj1vjFz{c*I4$Pe(+_V|^b~S!0xm{8lq= zZv)@NlcyL3Xdz+*|L137F7y6L-2VsrKw=q^S>F6i%<{Fr8zk06$Ay-(!L$fY@7mcng!2}L0t zgi|KxfB63Xtk_Q8#ZPipQ@!zgjdpEIbK_?q17Hoi4Eiyun$hrc>T(7pOLVLQE=lgGwA+A308p& z7@=09(|$>eLy5gLe{*|3b(M;1n;C^~v?o88jYib48eR4$QGsBFzd}3QuwO^_XE(=B zq+hMi0UFC|dB{LCwch7;zYT=NK})O%sgi0k#yV;My@24^B1+CuZmYOh0^b)5Ba_)) zC%i#_Iev&nsu%I|1N5=MVc#PrlunKAs&hY|3s5;@}`>sB>}gzxuB zB=2vrRyB3uiyW(hkDUNe1@&(b`;>ZvGgw|@s{zVC#_`HXIN_^J@Etb zA7A+F?ot37T{<-vTy8h&b3e+WKHE1oh;pUQrN4yRRrx?mT_9jRa2i4l1fUnLW^Cbl z!I1>VzyFe?VELWWhM?@?t-YPZkD-Qjo@bC2(o#ZtZmr{KZsdFWItV`rs$gp{724@C zL8K5}E0+DHcWcL^{BGei4>@J-3%a#$y6;I}=upc};-NDv-z#kPX26ylOpH)Ov1uU{ zkLj6oiH6l_s+B~_z;|Jc2oi?naS7#3H63~~lWj4rUnd=fCnKdkik<@R&kch9q##G{ z4u!%=rlM~Yp3jk*t8}1B`Sv6<%Z^}~1e@aq zg|JQ`QO2pSjAm-g*?IrNc$^~sIrNBo2$m|Sxanr?Mfs>2@Auu49 zGXlsS<9XS1&8h(dD*Hl&5HBDG!^pJ*lkau_Ur+7`7z;rcs$hT4we?3bT=7Fe<>{5( z2m2(c+hUz2BTHM8dCe*Z3XX&Av;b~a=$6EF>&^E8%nyxO@m_n!q&XD^A{SRjRZQ0L~qDeC=j&0$j6=LNIz@`ni^>ch|sv}^6 zlm>?28yPl@WmDPR?Y-A9X{U9Dv_IsbXJnzKCjkRksLOg#42uG2mE_acbTQ4)J|1V>%U@K(FP3AYhL0U zdeOCPN1qLv!|#c=p!_+%VNV(GHt`RuLRV^vz<5tt-r)yOK**kUWPspVAf|}ZL{LS= z@k(@@!P&W!>wwe`x{+GrFSWhHov7hu?{KuuT%kl#WO@*WX$i_@retlhQBj++SVNCx z5$78LxP>Z=^aJ)D280r_jj=zFfMJFXCIe^B{~V@d1rl_F(qo&AB4bC-vYL>x2jSKX zpuTG-6kgp3e^T&+dtV*i6a~)v@n?n*MffN59y}<0djUX zt27R+SE#hp8bzc#;rk$jw3r4)Q@eI$*`_)=Pvge8@8|8>H3X)<9YX6cXa=ii#Le;(qKm@%0-7$>2ShnYc`j#zJ7gu_FE^?uAkL|H)UIH#gPu^40!6^J=^ zr`}iwa^!4tzW~vOMZAaKF>*8A{^8m$i(VK)>?=#l`xrVe>wseSvM_aF zATNkY>kM_P3?1kE`uIq#mvr-wuTgUH0N<&JhF=(E9%^NS*HLm!4GZ4_XI zL=R5tlG5Mk_1rPfg)sk^llFuKPMPBhuU|L5q#yP_mzxp1o&pAzi-X31sgFpIHn@($ z_>=`AB5(8tP6p2zS5VEvH5J$M` z_much3>S7t3Yo`Yx!>83-hW9LYzDKP?mKdkD#QAK8*M((sx{eBQdrR<^3ZhFP81+& zBnJMUefQyNBji~$5d88Wfw1Lv59aJN9t2!pABLg;ewJ#LXL-10;QcJl+Y4Mtngb)k6JZlCf)3uD_u)J3sYyN;NN5hNbg$%W!i-GK%e&!Us)2IExWSss$YG(hm3kJ-h%yD z>8q^n$+4I(_y_mbT{du4P%h1j3oSpjhY97{+IZ`aA4ug!vNJ6*p?<2H(2w+GD3j$I z1TUXGyNzdf>_yB3grP~FZUs<2Quw;eEi*7s(-MiIkQ%@J^+WGdQvYSUN+TRiD-xto zJ=OUU+kxGYc!HCLNbCvR4lGTp~#L;DFzGd-#gJe*xf(P3hDQz|y)?b9mwU3WUVnpcqXM<@w%r-k*Wr^gzAv)8T^sqA=Ye z!7qy&exJmAcAt~CwS#@yNmjr8*T*!A6w4~E*ibaLRs0CFo(;R3=ODhDt6zWNodmo0 zXx&bT$6&+5c>a|WJ)F4G-^GjY0H#*tY=UNyYr_q5fsrcjk(c^~e*7Lf`!Jd`)p412 zn|^*hV= zFI4UbwA%X@smDd$cQOiMC%jfitTxTb+#`9`G=2rJDfK!E=5ra|So>lc{X1$~w28i+ z4p&cTGwZ#5VueiXS9O8#;RR$yg7tL9!^)Sz&pZYIzlSh}0}V{LxL$Cu%B4U5_}k}- zm~|CsD<076x@<>m=6w6N?WaThIBP`!u{-;WF)xc=2otx*lwf|5+MkdJePjh(B z9SH+%cHGCMAXNxB{_3^otDWdsV7Ob6n{0 z+&!(;iaHOX__5z_$Qk{%xYV%Ig@7iokGBwR`3642ZP#H#v9QGbWl8<|MS*=@qO@Uj z6+SZ_v9`1paUe5tFN~v(b#J3a_Lx0+;r9giZIx-A5TxdbG>xi#AZ5_z1V}B^n)sxT zz49}eK7EWb6wR!6-qQOrHQHkUvshvq%=G2d&@(#XM*Am1;WbnJ{X_!a{ZkphD$^TQ z=Iskb&}=lBm(RHiwJoGg`*NiQ6#RB$T#LF+>#ef;Jne&MxKPX!#r`&TVEFsp2jnNx>dClzpcPy&G&13a_<0qaR3i+k212~hoQ z8nMk{JP-t04I{GW5gUBqcJW-jSMrlw}>p)ptx?WKuCUV77taMiV zHok9V=6yv+Uts@fMY&A}amC=!Yj}eL@=e%XJ#%?agkt1jWF+10{(E9mHLDa>Ll7Vj zG=3cp%ljIB-6pC}6&`xJ*6WCP|IlglLWJ^?yviI8Ve)?V_i4%n;olzny62_`-|IGi z^=}p_O>Z8M;c4|RExu70E7ePW(HWVS&E$+LL6xSQgB`QfMQJ|4pCTFowA39p5P-|$ zUtM_H2HnP8_RoS~Vwk(FhbG zH41licj%=0a;Ln2STFBvU}Ne&O&%8bYKj!h1FA#sNM`232fX|U3QPp#3C?mN2;hE9 z;)!@5ixSPl<89^7gwhHc2YAX1KJK$#*3`KOMIQ253q7-*RJ5k)zp9GBO|Ga~X*^}US5oN@aG&waHV%vi~r{t^`ptTxb zL}q1W8S7*>7oWwvgV4uFLZ(@k`R*=LO_|Gu`prs~!WQXj-NLIa^2(7IHg>BG^N zc|i{-^=&Cek9dkJFQys|sjG9i>LLz|;yCv{^1i%c*h>8zF91kLvS9HBQi~ZU!JL`B zK8N+U0fr1*6??Ium)AF!6tc1eGhXIYL6IRT7rmKp7+>?%5Pa6zC5)KY$ycF0ZJ`G5nEQDG100U-jLkH8^UE4g6wq?sg%pP=-$&G#bcN`^?w3a6 z((s$6eRKcSEIslW-kk5Qi|5Mg-(xdLF}PxxVh$PuO}#aR6pW1kV4Af!Bqh*btXNNZ z>-4(IUl+L4dw+3LcpGut=qB45O+W)Q5?*zZ2A6rJcg`qkSvWA!j^r2mqKuCm6`Py? z@^T#Ux04HemPGd!Hs7NkZdVn1}8_j`o?)*OKZGS!`ff)gF zG?v-lj$wWNWCcw2Mg2o18D~1?3_b0XzdiKBNkYSDpcv@&kp0POmweJE2ZkIQ3B!a! zIgIoE+Xv?;34kyo^QYjZk+tEqZvq^#QG(OzX4~X+KtsoQoddTWUR(yo8R+ObEF1j<-syWOb>)JQ&Zbdu(sctU%Mt zW&YR0{ttY2TTXYZ?~WNU&cES1Z2q(7SrWDh``!J(JM+Nk$!hu&Y;(7E`ZNKTe0w+% zJc?Qnw2B+%UR}0;cB0Rufa(7-3FF}?629@LgTiEC&2uyL6NxexOp?AKT^aAx3gi(W zao>r>MPw0eQ3>IV02uLsC@>yK_epX6GRg4{NEL2wPPF9=*L2RV3yyK8DhuEK>rmmV z`&Q~#c`lgR&93TdOCja|ewOXmPNRh7!&dMT(1ett#iDr8HZW~VqWW@7fe9B6;7S+? zbC`d4@MEau&mKlOPKd>*10q0c{~^baw6!a*w^sY#0Xim{oOsiXiDOhbG&kl3c$$n1 zMRrD83&QucDSEcV*7LIp8VTA@F<%qe+_c`L;6on(>SjAU^}5c9!BCffT>$VQhe=)z z8(=Ej{5>jhmjB3{xDfj2R@VmHQ!CqjlO4KnuOmvHy3K#po$yp_V;p_MKjh1`(rzj6 zHW956k1yvntz{_g?Xbs`avK(IjlTnsu%htO;D7 z?J#x^EzuvVn&NA=!MEj7cwe5A-Z$Zk2LBZH$~%E* zf`((xH0?`}hs|HA%mtwfOEsZJxxrennkTYcwP#FKO5%Lpc^JXhSpV|ZH$Wr;`}`_( zIP==gd3LYyVtwD|*ZJGi{7~x8{=^bGVqu0RJ`n_BZH9+}kz%-4ZRsImi@rx%=ZEKs zcPnUXo6hbJV>fH;@1|bAHIe0ijYI*&kdT|HkDS$9No9 zCHo=*HWb~U+Dtzxr+Esao}6@|;Pf+E$ay0$kQp#s{wlw+7aIKbMdf`OqhoG*;Tco0 zjrP}VQG#Y2cJuqoJg&5({)S(BA}q9T1lGeWRyu=Je|)I!6a+aj!IP^1({)ZYe&x6w zt3a)Dq^TB+A7CdB0-}#z2Ur$W&h3YVw8==!xONy$uQmDWh-@15iEOt!q2m&?ZLA|w z8loSb(0}7y6Xu0?M5Uf4>VZGluB`wMf2oh;m)ghxVda>3m}4%V)r^0nVQ5V6f3>*) z0&VN!N0~GC^P}vj$`EDMZEmVV;N&RISY2C;$0;2(<{Lt&PKzqRByQdiEHGAbwtbS zPj`Da5%U6k1oEtVzI}QNw;!hT6F+~|@=c@$C4NtO@=xgP?|5MyZAyuCzcvq4rdAv@C06%gZ`9%I);R6UGiGJobfux+<0DLS&|MSG4UH z_~o{^^9>ixMg~mY!-@Fai{xaE4^;qy9iZN15Gbn5ZqHWf>Jc5Rv6(#n8`1NcCsdmG zab*dSXVPaE?)wCalD;$ivF%@nB#7D`@YG04p6ed9m}4iJW|pfVMLE<-c{=-8$e?cH zUdU#mCj4gb zZKA^b9p*9S(}8@tw~1RNPHr7tQr;P+-)D8|sq=*o)G%RGqt> zzP5yf`pVxb)I51D_G~Xp^GNK zVI6sAX)a9s)e{8N3?35YA6aQTXuyszK3ah~CemzA&CII#8F&F#KN41~8I^&_%}6MCNb{W87qAF`zj_Y^szhb> z3p3}KbOxotY|(lD=;)`fYE_*{S}x;f^SW#)SU&5X#o|-R|trpa|L5PS5aa0 zTHw8%SDSVtU4?vyrhnq+^@dgFS)|(y{~(4j%3UEiO-rBM9%`)8(dh33pMLiuurNY# z#10AsQ7%*0Cu_DSAU}P;X(JwA64~Q_^R%d_zSm^6Aux?Pn70PM>9EvLeOX z&w9c)pGmcL22;MO3C_B>=NC0RJpMp8?#ZUf=GWRvy z6RHq3B}=MGVg?9@iKFBpsvnkVh3{Vpp=`CcD=u~@ql{my|6?3ssi3mCOPnjI&E}VC zc@X+Yl>;;DNo0W0`0th!X{?luDhOC{E8N=?!w}K1{V=)+1={m(f`Oc|N=07>}3;z{-(A zm{JL=j?Sro5iecmE2-pWlRf(r%|HEQ7kgwQ9+kt=NBhtQI7OwcZ#3%$Uf%^r2nhjY zoQ08MfC%_X{O9~WcirMZMhn#z^ux4Erx-tf-6bHD)9eH&^L>^jvAd^9A^DCDs?0;k zkm7LE*KjP6`2d17MrQaaLqd_Rka}J$csvUec#hw78<=s(hyR>065~YCVCA9+#Q+; za(*L0IEw!r5P|@-;x33L$Lv9 zcuN8YG&g{<(SeJG18~(b!5yywSqQiLAX0;---;}mF5&b4lg|T?LwKREa{9YX_-zL@ZE?Zqi@HxK^2KO1>0LATu{te=T zprmHtY)bDVfxI1S}KBE7V zznP7KQ8HekWU#W6mw`dr-boV}pMQR==&5=Q5T=_q091jfc;R*jX#&=MQ%~@E@9^?`$v48ks<>(fI(F6L(5ppKy|$HWng*bKOb(4|cMUB&z$#ob#XV z5-mg)gmFIybZf=znm3ZPyUO^GJfxt0kmHjaTZ|sthsxXw&}Y)fOUSg=JhRSR^UjZ- zhqqb}Wsyw4zdnj6@#BAJa#-PdI4_dgafFXh85DsEQ_cT+5)XpZq$fZlBA_9UsE9r6 zEFec5?uqN@QhJ^IzwZrwl-5J`CmVPv{(YDTqEqWR^dI;5hXc~cxP%B3v&~s0`Ct89 z@S`i~a^c%V^N81dDT*ItFS*&IN;@O$EgzX0e7x&}TD=!zS}hTpezBLS>mdX(5< z)8DEI(-o_D)c-UX@dA1MuJ*yc>Hf4|`*B2S_O>w*-tbUwtiu`;W(Ud{HTty@(&x(T(F&;M zJ=?H>6`B7nf-90e8V`WSVp|0oEKB-P2M{}4ZDawzvM&a!y>`Y#jCsD%T_l``@ah(I2nJs~Q|%uSKu@k!m~*8B*IoA{*TgtF<(5sHCGG;n@NE%~Xt(G$^&<87u;}Na zx-8cq0g`uA(&RBFo=-4Y1GUZ<``Zw{xL4jfHkZw~%~wvtGueszcXt)_QwH8g!; z%s&3kSa~R$dO$-%L-)c@_hi7&>{6L_M>OZFkUQu;{sL_bUMStNrt{{&O(Wn~*zPOk zB>dnfszb29NSTf2pqIs68k|p-UrSrxgLHqi?3N-UFa!LHy9n1)=s>`yS+J{MEzS@ zNlfGtpma7kG&LR3JE@wB%rFA*h~~KitlO=IP)ZjN6dQLM6qsry zHkB#cyNh#n`)}bCrN1My*;k)^@>e4gJ`LJK?2)Pwp?4Tl4)4FA0(tvY+#1jOUM)xw zlMz4x-f@g^+yKUN`?Vu)|AwujArnM~Pa@y*Q9S8eS(u{-S%(Z5=R~pRl5ZGDjdqH% zC8rW&{##wOpU_oTIG4WXMk4&%2t1;lWcW5&!yxmOT*!hBcKyTqEcNoO+R2;Q?Yj+W z1-Y4?59fijz4(MIDwGe4-baYf08UCs;r|YefD-Md2ST;=cxwpgW=tR76-dQVAhn^= zG9Wk5lQk%jIR@KNU!UMp6@BfU;r+;y4VQ)D2!Il9HX%yW-9nOzV+m$YKzVaO`B8S7t z$!S2Mz`xw>V(RjE`0>bQp<0y&h~Y=M#jpy!#=dE>`=e_AjSZq6u!Dy1xJf~-7|0F! zPR9|n`e_7D2DIV2H(CESQ}hA>U>n|6`%z?YKEA~)BOVY%y=jPV zT=44R!L?J)736X#csn|lfBJ)o8ixaZclguWgrGO<`TN2FMfO}7;5}d+BlK0yTSH3* z4!=;5rOh85&2|x=46hkNaz?)U8&=bcfh=N_#8BNpZ2v$aVBo;sk^*X`v;4-LU;D>! zM*h12MxXIQy)SfAqE4;jY)wgnppazZkdNNVVF;(PLf^qK$FgY9+VFyBKE7UC|f z`R|?&egV11K3s$rJ6!GvoeW=jV*!-e(wA;x(2=d0E_e_%0x--0o8#~m^H1%AH5Z^B zn!TNPn927*bvaf0pt}zhK0o^V@WlGwwKo(*nQ|Q~4_;>~-8y20`HP>@UJa)3nEnGG z5Hwhs|FcmFG16ZVNb5hL`2Gc1{zWIMM{_OiKewV!hCi}U!VuE?s9wU-QbZ!)+Y^tS zGzp5OSi5iq6hmEr$w}&9DFgoB+i*`q`8TBi^MVS{SKEb8Aw%@K7@XCo(De2A`6%mf&a2#~y1N)+kJLD$1HCP!22)(U}xo2|j?WRzt(11j8Z_*v;P$R+Ug*Gy3VxV4K; zGGUGabnW*`Z}~`ydXL-l9e=GC$pY#z|63vy>E*m=$=j}iWP{sRTh0%H54`t>2xYH% zsk+M&u&pNgMCM@3e)Xc?jBWX-TIR_cQ1Z!RW7!B zBjZX=+^3}?SE)B+$EP+0oi1Fp5blDT?*}nsP>filqXH{ms zxU<$hetC`u)Wi+x|EKL-`y^#aQX+sDYIa{M;V%LqLrOk~lR>u0Q!+pyQSU4zY`?E^ z|5@)C)w6G_=i5YYC5SE_u(7hDNYr}uKT|@DSqF%S++lTIbIk^$a>{~0IH8KNFEy%+ zW#$&!ynpgNJh>6uR~?2c)ZMW+h0OKu231(7L_vETPaR+(P)Zy%0~yGm>E9?@@x!Jy z3PYgS}Q@b}x}E#F27@F+j}0=&Ql4gES&f8acMrPAVlVs9$97`FR))R5wI zc&}KFI1UIewh>3PkhnB7u zS3AT8_*|nexznG|Z*DU0c!K@jsI4J)5#DyNi#|e#`l1Vv1`1)*NVcy0LZ``aL0n8B zecupJ(rhq3u8bW0NIRhKYq$v1li+jp*4hfAd&wxYDE8vn1TQ7S@bTM|I2Ob z8vMOIxA7&_j{AKmD+O@EyXT`|dElt0pED^@IV0m)RPBUs*5jW60>>w1!@_G3aBKzG z_f(KfAPBk}-jQtR*Sroq!*3rbQ_m27e+YdzQjUb<_*k8vc_C)y!@cj5E>NxUhPu&g z@Z2<~esU`)ih+4opWe+K7sbN9n*9@n>#@n3*o z?xoROgDuvhq>jJ;Ve{6i<3roQNfgo5^4Q4(|GNExO2Dr7GjgA2zWuKp_K)K0R(6lv z!l$!zW-+T6mb3gQaAFviTQi{|*t%>{(mhTdy+y;Re4qT@kccy#{b z&zWy~kLO@>*WPj2k#H)|7L&gAJ37DmHQAme#@m;(Y8Nu^`D5vf8sZFW#+lA2!HK=( zJ)#hO6JD*`o~&c*&46d}g=Qj@SsoB5ikC z^1V8E+&<-OzuS_C`p5<<(A6fB`LXT(!kV^0_~hL6PpW4={l%|#xgdh?5EIk~lu8{D z2hiyhv3Yxij_#$Wu>P@7SYsl`-~3;}Ktx{34_NL^Kwin&=?!HDv3elQDbcU*qyYpN z(#yw~f1vFGK-t%CC-qa-4FYHbA^h>bag-I&*qaxwn?Qv|idE$<>1H|Gr6JtUu(he2$eg!N z@HTF@dG1)*y;4fxe)4_ZkpaBHH9hXp9p4|gLrRQyuevRd@gSS}JhRnWqrvm|U@>qM z=yl7RQROTKwQtzP3!zUF)_6Ld#NGA6v~2{J9Dd`h6{%+XsU#qGLh%`fB1Hc?wfayK zN`H4BpDp)npVQuu$DVW1qsBS&AJ2eP%6Qw>;k{)Z$8%HL=Q4(a$Ng2_vHw&vA!1L+9zc8vaX2GtqJ{L-;gvF0IR$em zMQ8@{Qp3+3Quk)TJ$?I<8KmwzD*7#(q<@Mc`dchngW}cRG14(Z6K7{T|LhFXwhqUQ;BET;cYqPcAcMgt6M$V9$(?jHo@Sud$an$U&5F zZ1QNh^ztt)E*d#Ij;<43oSKKnd+WNr$_r}+s_O_x6DZSB10*5Q{ourqq>mTl| zx4y^(cy+9;t@R=*j>3_dmm_m)$k$#937V(sllby&5)Xex^UD-|m|q<(jEd#@DV(of zAd7sSdmS*zUDqJ9|K%O2J2OfdUiK{{b{PCy)pi<;hp~7v1CQj&4-10 zgO<3dqhYH1#-Fa}Q{pjql5>>P6gZH21zLfxZ4$SK4T@7b!|`nWF9b*84Bq8&Eht;9 z*P72x&NUCZ7*@B$`FtE=hz5b}S`|c6Ey+j@D1ZibjJaRlR;{cxAWv z?Nqa>QqV*H-*zzaPvpLMHt~nl(x6?vrPpR?zn7~wow?oj*1TKmx4j71>$hvtC$DLD zUrz0^tiP0792U&dxJxNv@r}Elsjn^aSLUu=9#mD{&9n8|ayIL$!H3s>%KEvbchBFW z%cd?VU83mGF#Dar9*s~w&AnmQRQIOvR+uWsuZ?+|a=TzApXO@q^(r%8=}iv#wCnFq z=K9}JbqU@k99Q%j-}NNk+qLCP)jXfmOO|)@?mHcnynd6({mJisP1_}u7k)|eYHXWK z63eQ)E$ufFi!3CWUY2gw%e>omCv}qEX66aH-k&35f9`Q@Us|NPetVqe8=dX*VxJdn ze`q7b=Dn(UA(2sf&g)cOmQFhNJ#<-aMELJZbA#@to>25@kbW<)&!X01 z%NMJt>1ST)tyX)h@?`DxhbgCHr>S4wv}WC&Nw-!{+Z7$2D}74QAcXTvip=M0%Tp_N zor=k`)t|ra^ySr-+(|R9mB(E=`MX#y(wSw)$!iymzB;^c*>%&^*7HxTnRga=soSZT zdDl+9s;r!v8hk6POtzBaig4pRp7eWF(<8gufvNHPu6xs-=e{;mnHzJyGKE+8L0j}; z@%8-e^UCL5HhMiR>sD3Rve&yVZ#{Q1*CO8c+qSr^Z#CN;)(X5>tGG5yUw3<+CfhaL z%bP;hZ?jvgJU67BWyiy74_)6r)_nSxttxn0`0?HE^5(uydHVgP+HE$V?Lv)Leti43 zWA|;f-RqX``95>)^P-fw!Vi{3KNsII-*5f){gdxqd%gVdB1sOBNe=nEW%;i~g_P8J w!5uhoe-Jcg1nPN%MiEAtgE$;km@@t6ukO)1^!cY^83Pb_y85}Sb4q9e0FIsP9{>OV literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/cross_file/cross_file_darwin/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1632cfddf3d9dade342351e627a0a75609fb46 GIT binary patch literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000000..41042182cc52 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = cross_file_darwin_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2026 dev.flutter.packages. All rights reserved. diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 000000000000..36b0fd9464f4 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 000000000000..dff4f49561c8 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Warnings.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 000000000000..42bcbf4780b1 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements b/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 000000000000..dddb8a30c851 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Info.plist b/packages/cross_file/cross_file_darwin/example/macos/Runner/Info.plist new file mode 100644 index 000000000000..4789daa6a443 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/MainFlutterWindow.swift b/packages/cross_file/cross_file_darwin/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 000000000000..3cc05eb23491 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements b/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements new file mode 100644 index 000000000000..852fa1a4728a --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..b38c13977aaf --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,28 @@ +import Cocoa +import FlutterMacOS +import XCTest + + +@testable import cross_file_darwin + +// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. +// +// See https://developer.apple.com/documentation/xctest for more information about using XCTest. + +class RunnerTests: XCTestCase { + + func testGetPlatformVersion() { + let plugin = CrossFileDarwinPlugin() + + let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) + + let resultExpectation = expectation(description: "result block must be called.") + plugin.handle(call) { result in + XCTAssertEqual(result as! String, + "macOS " + ProcessInfo.processInfo.operatingSystemVersionString) + resultExpectation.fulfill() + } + waitForExpectations(timeout: 1) + } + +} diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml new file mode 100644 index 000000000000..ddfa58a46941 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -0,0 +1,85 @@ +name: cross_file_darwin_example +description: "Demonstrates how to use the cross_file_darwin plugin." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +environment: + sdk: ^3.11.0-268.0.dev + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + cross_file_darwin: + # When depending on this package from a real application you should use: + # cross_file_darwin: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + +dev_dependencies: + integration_test: + sdk: flutter + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_darwin/example/test/widget_test.dart b/packages/cross_file/cross_file_darwin/example/test/widget_test.dart new file mode 100644 index 000000000000..7250974c66e6 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/test/widget_test.dart @@ -0,0 +1,27 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:cross_file_darwin_example/main.dart'; + +void main() { + testWidgets('Verify Platform version', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + + // Verify that platform version is retrieved. + expect( + find.byWidgetPredicate( + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), + ), + findsOneWidget, + ); + }); +} diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart new file mode 100644 index 000000000000..50699c2e6ee2 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -0,0 +1,8 @@ + +import 'cross_file_darwin_platform_interface.dart'; + +class CrossFileDarwin { + Future getPlatformVersion() { + return CrossFileDarwinPlatform.instance.getPlatformVersion(); + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart new file mode 100644 index 000000000000..cf66719eafd6 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart @@ -0,0 +1,19 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +import 'cross_file_darwin_platform_interface.dart'; + +/// An implementation of [CrossFileDarwinPlatform] that uses method channels. +class MethodChannelCrossFileDarwin extends CrossFileDarwinPlatform { + /// The method channel used to interact with the native platform. + @visibleForTesting + final methodChannel = const MethodChannel('cross_file_darwin'); + + @override + Future getPlatformVersion() async { + final version = await methodChannel.invokeMethod( + 'getPlatformVersion', + ); + return version; + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart new file mode 100644 index 000000000000..fff02f8183dc --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart @@ -0,0 +1,29 @@ +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +import 'cross_file_darwin_method_channel.dart'; + +abstract class CrossFileDarwinPlatform extends PlatformInterface { + /// Constructs a CrossFileDarwinPlatform. + CrossFileDarwinPlatform() : super(token: _token); + + static final Object _token = Object(); + + static CrossFileDarwinPlatform _instance = MethodChannelCrossFileDarwin(); + + /// The default instance of [CrossFileDarwinPlatform] to use. + /// + /// Defaults to [MethodChannelCrossFileDarwin]. + static CrossFileDarwinPlatform get instance => _instance; + + /// Platform-specific implementations should set this with their own + /// platform-specific class that extends [CrossFileDarwinPlatform] when + /// they register themselves. + static set instance(CrossFileDarwinPlatform instance) { + PlatformInterface.verifyToken(instance, _token); + _instance = instance; + } + + Future getPlatformVersion() { + throw UnimplementedError('platformVersion() has not been implemented.'); + } +} diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml new file mode 100644 index 000000000000..f712849a7e4e --- /dev/null +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -0,0 +1,73 @@ +name: cross_file_darwin +description: "A new Flutter plugin project." +version: 0.0.1 +homepage: + +environment: + sdk: ^3.11.0-268.0.dev + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + plugin_platform_interface: ^2.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + # This section identifies this Flutter project as a plugin project. + # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) + # which should be registered in the plugin registry. This is required for + # using method channels. + # The Android 'package' specifies package in which the registered class is. + # This is required for using method channels on Android. + # The 'ffiPlugin' specifies that native code should be built and bundled. + # This is required for using `dart:ffi`. + # All these are used by the tooling to maintain consistency when + # adding or updating assets for this project. + plugin: + platforms: + ios: + pluginClass: CrossFileDarwinPlugin + sharedDarwinSource: true + macos: + pluginClass: CrossFileDarwinPlugin + sharedDarwinSource: true + + # To add assets to your plugin package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/to/asset-from-package + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # To add custom fonts to your plugin package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart b/packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart new file mode 100644 index 000000000000..fce69ec2e774 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart @@ -0,0 +1,26 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_darwin/cross_file_darwin_method_channel.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + MethodChannelCrossFileDarwin platform = MethodChannelCrossFileDarwin(); + const MethodChannel channel = MethodChannel('cross_file_darwin'); + + setUp(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (MethodCall methodCall) async { + return '42'; + }); + }); + + tearDown(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, null); + }); + + test('getPlatformVersion', () async { + expect(await platform.getPlatformVersion(), '42'); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart b/packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart new file mode 100644 index 000000000000..ef7f36f8f9c8 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart @@ -0,0 +1,28 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:cross_file_darwin/cross_file_darwin.dart'; +import 'package:cross_file_darwin/cross_file_darwin_platform_interface.dart'; +import 'package:cross_file_darwin/cross_file_darwin_method_channel.dart'; +import 'package:plugin_platform_interface/plugin_platform_interface.dart'; + +class MockCrossFileDarwinPlatform + with MockPlatformInterfaceMixin + implements CrossFileDarwinPlatform { + @override + Future getPlatformVersion() => Future.value('42'); +} + +void main() { + final CrossFileDarwinPlatform initialPlatform = CrossFileDarwinPlatform.instance; + + test('$MethodChannelCrossFileDarwin is the default instance', () { + expect(initialPlatform, isInstanceOf()); + }); + + test('getPlatformVersion', () async { + CrossFileDarwin crossFileDarwinPlugin = CrossFileDarwin(); + MockCrossFileDarwinPlatform fakePlatform = MockCrossFileDarwinPlatform(); + CrossFileDarwinPlatform.instance = fakePlatform; + + expect(await crossFileDarwinPlugin.getPlatformVersion(), '42'); + }); +} From 5db6f0bf73a260418cae5db037bd8b6819cd32f6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 9 Jan 2026 14:26:43 -0500 Subject: [PATCH 074/398] update pubspecs and stuff --- .../cross_file/cross_file_darwin/.gitignore | 33 -------- .../cross_file/cross_file_darwin/.metadata | 33 -------- .../cross_file/cross_file_darwin/CHANGELOG.md | 2 +- packages/cross_file/cross_file_darwin/LICENSE | 26 ++++++- .../cross_file/cross_file_darwin/README.md | 20 ++--- .../cross_file_darwin/analysis_options.yaml | 4 - .../cross_file_darwin/darwin/.gitignore | 38 --------- .../cross_file_darwin/example/.gitignore | 45 ----------- .../cross_file_darwin/example/README.md | 22 ++---- .../example/analysis_options.yaml | 28 ------- .../cross_file_darwin/example/ios/.gitignore | 34 -------- .../example/ios/Flutter/Debug.xcconfig | 1 + .../example/ios/Flutter/Release.xcconfig | 1 + .../cross_file_darwin/example/ios/Podfile | 43 +++++++++++ .../example/macos/.gitignore | 7 -- .../macos/Flutter/Flutter-Debug.xcconfig | 1 + .../macos/Flutter/Flutter-Release.xcconfig | 1 + .../cross_file_darwin/example/macos/Podfile | 42 ++++++++++ .../cross_file_darwin/example/pubspec.yaml | 74 +++--------------- .../cross_file/cross_file_darwin/pubspec.yaml | 77 +++++-------------- 20 files changed, 163 insertions(+), 369 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/.gitignore delete mode 100644 packages/cross_file/cross_file_darwin/.metadata delete mode 100644 packages/cross_file/cross_file_darwin/analysis_options.yaml delete mode 100644 packages/cross_file/cross_file_darwin/darwin/.gitignore delete mode 100644 packages/cross_file/cross_file_darwin/example/.gitignore delete mode 100644 packages/cross_file/cross_file_darwin/example/analysis_options.yaml delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Podfile delete mode 100644 packages/cross_file/cross_file_darwin/example/macos/.gitignore create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Podfile diff --git a/packages/cross_file/cross_file_darwin/.gitignore b/packages/cross_file/cross_file_darwin/.gitignore deleted file mode 100644 index b9d7f25b91b6..000000000000 --- a/packages/cross_file/cross_file_darwin/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/cross_file/cross_file_darwin/.metadata b/packages/cross_file/cross_file_darwin/.metadata deleted file mode 100644 index 80c51c8a98e1..000000000000 --- a/packages/cross_file/cross_file_darwin/.metadata +++ /dev/null @@ -1,33 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "08e122f466ea6b49c266bb09869618d9e50a0119" - channel: "main" - -project_type: plugin - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 - base_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 - - platform: ios - create_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 - base_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 - - platform: macos - create_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 - base_revision: 08e122f466ea6b49c266bb09869618d9e50a0119 - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_darwin/CHANGELOG.md b/packages/cross_file/cross_file_darwin/CHANGELOG.md index 41cc7d8192ec..d0bd041d0ff6 100644 --- a/packages/cross_file/cross_file_darwin/CHANGELOG.md +++ b/packages/cross_file/cross_file_darwin/CHANGELOG.md @@ -1,3 +1,3 @@ ## 0.0.1 -* TODO: Describe initial release. +* Initial release. diff --git a/packages/cross_file/cross_file_darwin/LICENSE b/packages/cross_file/cross_file_darwin/LICENSE index ba75c69f7f21..29b709dac6c7 100644 --- a/packages/cross_file/cross_file_darwin/LICENSE +++ b/packages/cross_file/cross_file_darwin/LICENSE @@ -1 +1,25 @@ -TODO: Add your license here. +Copyright 2013 The Flutter Authors + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/cross_file/cross_file_darwin/README.md b/packages/cross_file/cross_file_darwin/README.md index e7b7591898d1..1c9e41b30df2 100644 --- a/packages/cross_file/cross_file_darwin/README.md +++ b/packages/cross_file/cross_file_darwin/README.md @@ -1,15 +1,15 @@ -# cross_file_darwin +# cross\_file\_darwin -A new Flutter plugin project. +The Darwin implementation of [`cross_file`][1]. -## Getting Started +## Usage -This project is a starting point for a Flutter -[plug-in package](https://flutter.dev/to/develop-plugins), -a specialized package that includes platform-specific implementation code for -Android and/or iOS. +This package is [endorsed][2], which means you can simply use `cross_file` +normally. This package will be automatically included in your app when you do, +so you do not need to add it to your `pubspec.yaml`. -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +However, if you `import` this package to use any of its APIs directly, you +should add it to your `pubspec.yaml` as usual. +[1]: https://pub.dev/packages/cross_file +[2]: https://flutter.dev/to/endorsed-federated-plugin diff --git a/packages/cross_file/cross_file_darwin/analysis_options.yaml b/packages/cross_file/cross_file_darwin/analysis_options.yaml deleted file mode 100644 index a5744c1cfbe7..000000000000 --- a/packages/cross_file/cross_file_darwin/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_darwin/darwin/.gitignore b/packages/cross_file/cross_file_darwin/darwin/.gitignore deleted file mode 100644 index 034771fc9c9b..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig -/Flutter/ephemeral/ -/Flutter/flutter_export_environment.sh diff --git a/packages/cross_file/cross_file_darwin/example/.gitignore b/packages/cross_file/cross_file_darwin/example/.gitignore deleted file mode 100644 index 3820a95c65c3..000000000000 --- a/packages/cross_file/cross_file_darwin/example/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/packages/cross_file/cross_file_darwin/example/README.md b/packages/cross_file/cross_file_darwin/example/README.md index 65ee88242c41..96b8bb17dbff 100644 --- a/packages/cross_file/cross_file_darwin/example/README.md +++ b/packages/cross_file/cross_file_darwin/example/README.md @@ -1,17 +1,9 @@ -# cross_file_darwin_example +# Platform Implementation Test App -Demonstrates how to use the cross_file_darwin plugin. +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) -- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/packages/cross_file/cross_file_darwin/example/analysis_options.yaml b/packages/cross_file/cross_file_darwin/example/analysis_options.yaml deleted file mode 100644 index 0d2902135cae..000000000000 --- a/packages/cross_file/cross_file_darwin/example/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_darwin/example/ios/.gitignore b/packages/cross_file/cross_file_darwin/example/ios/.gitignore deleted file mode 100644 index 7a7f9873ad7d..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig index 592ceee85b89..ec97fc6f3021 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig index 592ceee85b89..c4855bfe2000 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Podfile b/packages/cross_file/cross_file_darwin/example/ios/Podfile new file mode 100644 index 000000000000..620e46eba607 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/cross_file/cross_file_darwin/example/macos/.gitignore b/packages/cross_file/cross_file_darwin/example/macos/.gitignore deleted file mode 100644 index 746adbb6b9e1..000000000000 --- a/packages/cross_file/cross_file_darwin/example/macos/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# Flutter-related -**/Flutter/ephemeral/ -**/Pods/ - -# Xcode-related -**/dgph -**/xcuserdata/ diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig index c2efd0b608ba..4b81f9b2d200 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig index c2efd0b608ba..5caa9d1579e4 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig @@ -1 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Podfile b/packages/cross_file/cross_file_darwin/example/macos/Podfile new file mode 100644 index 000000000000..ff5ddb3b8bdc --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index ddfa58a46941..f2fb299676c8 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -1,22 +1,12 @@ name: cross_file_darwin_example description: "Demonstrates how to use the cross_file_darwin plugin." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +publish_to: 'none' environment: - sdk: ^3.11.0-268.0.dev + sdk: ^3.9.0 + flutter: ">=3.35.0" -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: - flutter: - sdk: flutter - cross_file_darwin: # When depending on this package from a real application you should use: # cross_file_darwin: ^x.y.z @@ -24,62 +14,18 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + file_selector: ^1.1.0 + flutter: + sdk: flutter + mime: ^2.0.0 + video_player: ^2.8.6 dev_dependencies: - integration_test: - sdk: flutter flutter_test: sdk: flutter + integration_test: + sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index f712849a7e4e..d17bc1e2e524 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -1,38 +1,16 @@ name: cross_file_darwin description: "A new Flutter plugin project." +repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_darwin +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 -homepage: environment: - sdk: ^3.11.0-268.0.dev - flutter: '>=3.3.0' + sdk: ^3.9.0 + flutter: ">=3.35.0" -dependencies: - flutter: - sdk: flutter - plugin_platform_interface: ^2.0.2 - -dev_dependencies: - flutter_test: - sdk: flutter - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - # This section identifies this Flutter project as a plugin project. - # The 'pluginClass' specifies the class (in Java, Kotlin, Swift, Objective-C, etc.) - # which should be registered in the plugin registry. This is required for - # using method channels. - # The Android 'package' specifies package in which the registered class is. - # This is required for using method channels on Android. - # The 'ffiPlugin' specifies that native code should be built and bundled. - # This is required for using `dart:ffi`. - # All these are used by the tooling to maintain consistency when - # adding or updating assets for this project. plugin: + implements: cross_file platforms: ios: pluginClass: CrossFileDarwinPlugin @@ -41,33 +19,20 @@ flutter: pluginClass: CrossFileDarwinPlugin sharedDarwinSource: true - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/to/asset-from-package - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images +dependencies: + cross_file_io: + path: ../cross_file_io + cross_file_platform_interface: + path: ../cross_file_platform_interface + flutter: + sdk: flutter + +dev_dependencies: + build_runner: ^2.10.4 + flutter_test: + sdk: flutter + mockito: ^5.4.4 + pigeon: ^26.1.4 - # To add custom fonts to your plugin package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/to/font-from-package +topics: + - file From e3d62f012296685caa602f8d0b81c3a8cbcd9652 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:07:16 -0500 Subject: [PATCH 075/398] extension doesnt exist --- .../cross_file/cross_file_android/lib/cross_file_android.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index e932bd8bf45e..959c5cae1a4e 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -5,6 +5,5 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show ListParams, PlatformXFileEntity; -export 'src/android_shared_storage_cross_file.dart' - show AndroidSharedStorageXFileExtension; +export 'src/android_shared_storage_cross_file.dart'; export 'src/cross_file_android.dart'; From 4e3c7071baba039768b1b31bc9cfe7b8bcfb0aef Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:07:53 -0500 Subject: [PATCH 076/398] file is not needed --- .../cross_file/cross_file_android/lib/cross_file_android.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 959c5cae1a4e..a74390acbefd 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -5,5 +5,4 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show ListParams, PlatformXFileEntity; -export 'src/android_shared_storage_cross_file.dart'; export 'src/cross_file_android.dart'; From f836480178e16cab674aff11b75eccf2e53e9e72 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:29:58 -0500 Subject: [PATCH 077/398] use uint8list for bytes --- .../lib/src/platform_cross_file.dart | 2 +- .../test/cross_file_platform_test.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 12d697cd6195..5703a83194fc 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -118,7 +118,7 @@ abstract base class PlatformXFile extends PlatformXFileEntity { /// /// Platforms may throw an exception if there is an error opening or reading /// the resource. - Stream> openRead([int? start, int? end]); + Stream openRead([int? start, int? end]); /// Reads the entire resource contents as a list of bytes. /// diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index f43aabebac7a..30f925867fbb 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -58,7 +58,7 @@ final class TestXFile extends PlatformXFile { } @override - Stream> openRead([int? start, int? end]) { + Stream openRead([int? start, int? end]) { throw UnimplementedError(); } From 8e187eea75ecb86a5a75f0504cd5f3ab0b1b603c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:36:30 -0500 Subject: [PATCH 078/398] change web type --- packages/cross_file/cross_file_web/lib/src/web_cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index cf2d307158c3..06d4ba1614a9 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -110,7 +110,7 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { } @override - Stream> openRead([int? start, int? end]) async* { + Stream openRead([int? start, int? end]) async* { final Blob blob = await getBlob(); final Blob slice = blob.slice(start ?? 0, end ?? blob.size, blob.type); yield await blobToBytes(slice); From d1b666ea04da4f20b3ced39e929969a03293acac Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:57:08 -0500 Subject: [PATCH 079/398] impl update --- .../cross_file_darwin/example/lib/main.dart | 122 ++++++++---- .../example/test/widget_test.dart | 27 --- .../lib/cross_file_darwin.dart | 11 +- .../lib/cross_file_darwin_method_channel.dart | 19 -- .../cross_file_darwin_platform_interface.dart | 29 --- .../src/darwin_shared_storage_cross_file.dart | 174 ++++++++++++++++++ ...cross_file_darwin_method_channel_test.dart | 26 --- .../test/cross_file_darwin_test.dart | 28 --- 8 files changed, 259 insertions(+), 177 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/example/test/widget_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart delete mode 100644 packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 0f92505796bc..c66ed1242f9c 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -1,59 +1,101 @@ -import 'package:flutter/material.dart'; -import 'dart:async'; +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -import 'package:flutter/services.dart'; -import 'package:cross_file_darwin/cross_file_darwin.dart'; +import 'package:file_selector/file_selector.dart'; +import 'package:flutter/material.dart'; +import 'package:mime/mime.dart' as mime; void main() { - runApp(const MyApp()); + runApp(const MaterialApp(home: FileOpenScreen())); } -class MyApp extends StatefulWidget { - const MyApp({super.key}); +/// Example screen to open a file selector and display it. +class FileOpenScreen extends StatelessWidget { + /// Constructs a [FileOpenScreen]. + const FileOpenScreen({super.key}); - @override - State createState() => _MyAppState(); -} + Future _openFile(BuildContext context) async { + final XFile? file = await openFile(); -class _MyAppState extends State { - String _platformVersion = 'Unknown'; - final _crossFileDarwinPlugin = CrossFileDarwin(); + if (!context.mounted) { + return; + } - @override - void initState() { - super.initState(); - initPlatformState(); + if (file case final XFile file) { + switch (mime.lookupMimeType(file.path)) { + case final String mimeType when mimeType.startsWith('text'): + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(file), + ); + case final String mimeType when mimeType.startsWith('image'): + case final String mimeType when mimeType.startsWith('application'): + case null: + debugPrint('Unsupported file type: ${file.path}'); + return; + } + } } - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - String platformVersion; - // Platform messages may fail, so we use a try/catch PlatformException. - // We also handle the message potentially returning null. - try { - platformVersion = - await _crossFileDarwinPlugin.getPlatformVersion() ?? 'Unknown platform version'; - } on PlatformException { - platformVersion = 'Failed to get platform version.'; - } + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a File'), + backgroundColor: Colors.blue, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ], + ), + ), + ); + } +} - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.file, {super.key}); - setState(() { - _platformVersion = platformVersion; - }); - } + /// The file. + final XFile file; @override Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar(title: const Text('Plugin example app')), - body: Center(child: Text('Running on: $_platformVersion\n')), + return AlertDialog( + title: Text(file.path), + content: Scrollbar( + child: SingleChildScrollView( + child: FutureBuilder( + future: file.readAsString(), + builder: (_, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!); + } else { + return const CircularProgressIndicator(); + } + }, + ), + ), ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], ); } } diff --git a/packages/cross_file/cross_file_darwin/example/test/widget_test.dart b/packages/cross_file/cross_file_darwin/example/test/widget_test.dart deleted file mode 100644 index 7250974c66e6..000000000000 --- a/packages/cross_file/cross_file_darwin/example/test/widget_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:cross_file_darwin_example/main.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => - widget is Text && widget.data!.startsWith('Running on:'), - ), - findsOneWidget, - ); - }); -} diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 50699c2e6ee2..b8fa2a34b670 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -1,8 +1,3 @@ - -import 'cross_file_darwin_platform_interface.dart'; - -class CrossFileDarwin { - Future getPlatformVersion() { - return CrossFileDarwinPlatform.instance.getPlatformVersion(); - } -} +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart deleted file mode 100644 index cf66719eafd6..000000000000 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_method_channel.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -import 'cross_file_darwin_platform_interface.dart'; - -/// An implementation of [CrossFileDarwinPlatform] that uses method channels. -class MethodChannelCrossFileDarwin extends CrossFileDarwinPlatform { - /// The method channel used to interact with the native platform. - @visibleForTesting - final methodChannel = const MethodChannel('cross_file_darwin'); - - @override - Future getPlatformVersion() async { - final version = await methodChannel.invokeMethod( - 'getPlatformVersion', - ); - return version; - } -} diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart deleted file mode 100644 index fff02f8183dc..000000000000 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin_platform_interface.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -import 'cross_file_darwin_method_channel.dart'; - -abstract class CrossFileDarwinPlatform extends PlatformInterface { - /// Constructs a CrossFileDarwinPlatform. - CrossFileDarwinPlatform() : super(token: _token); - - static final Object _token = Object(); - - static CrossFileDarwinPlatform _instance = MethodChannelCrossFileDarwin(); - - /// The default instance of [CrossFileDarwinPlatform] to use. - /// - /// Defaults to [MethodChannelCrossFileDarwin]. - static CrossFileDarwinPlatform get instance => _instance; - - /// Platform-specific implementations should set this with their own - /// platform-specific class that extends [CrossFileDarwinPlatform] when - /// they register themselves. - static set instance(CrossFileDarwinPlatform instance) { - PlatformInterface.verifyToken(instance, _token); - _instance = instance; - } - - Future getPlatformVersion() { - throw UnimplementedError('platformVersion() has not been implemented.'); - } -} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart new file mode 100644 index 000000000000..515d19990d07 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart @@ -0,0 +1,174 @@ +// // Copyright 2013 The Flutter Authors +// // Use of this source code is governed by a BSD-style license that can be +// // found in the LICENSE file. +// +// import 'dart:convert'; +// import 'dart:typed_data'; +// +// import 'package:cross_file_ios/src/foundation.g.dart'; +// import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +// import 'package:flutter/foundation.dart'; +// +// /// Implementation of [PlatformXFileCreationParams] for iOS and macOS. +// @immutable +// base class DarwinXFileCreationParams extends PlatformXFileCreationParams { +// /// Constructs a [DarwinXFileCreationParams]. +// const DarwinXFileCreationParams({required super.uri}) : super(); +// } +// +// // Note for me: Will probs need a `static Future method(Uint8List bookmarkData` method +// // instead to create persistent file. +// base class IOSXFile extends PlatformSharedStorageXFile { +// IOSXFile(super.params) : super.implementation(); +// +// Future asBookmarkedFile() { +// final URL? url = await _originalUrl; +// if (url case URL url) { +// final bool canRead = await url.startAccessingSecurityScopedResource(); +// if (canRead) { +// try { +// final Uint8List? bookmarkData = await url.bookmarkData([], [], null); +// if (bookmarkData case Uint8List bookmarkData) { +// final URLResolvingBookmarkDataResponse response = await URL +// .resolvingBookmarkData(bookmarkData, [], null); +// if (response.isStale) { +// print('STALE'); +// return null; +// } +// return response.url; +// } +// } finally { +// await url.stopAccessingSecurityScopedResource(); +// } +// } +// } +// +// return null; +// } +// +// late final Future _originalUrl = URL.fileURLWithPath(params.path); +// +// late final Future _bookmarkUrl = () async { +// final URL? url = await _originalUrl; +// if (url case URL url) { +// final bool canRead = await url.startAccessingSecurityScopedResource(); +// if (canRead) { +// try { +// final Uint8List? bookmarkData = await url.bookmarkData([], [], null); +// if (bookmarkData case Uint8List bookmarkData) { +// final URLResolvingBookmarkDataResponse response = await URL +// .resolvingBookmarkData(bookmarkData, [], null); +// if (response.isStale) { +// print('STALE'); +// return null; +// } +// return response.url; +// } +// } finally { +// await url.stopAccessingSecurityScopedResource(); +// } +// } +// } +// +// return null; +// }(); +// +// @override +// Future canRead() async { +// final URL? bookmarkUrl = await _bookmarkUrl; +// if (bookmarkUrl case URL bookmarkUrl) { +// return FileManager.defaultManager.isReadableFile( +// await bookmarkUrl.path(), +// ); +// } +// +// return false; +// } +// +// @override +// Future exists() async { +// final URL? bookmarkUrl = await _bookmarkUrl; +// if (bookmarkUrl case URL bookmarkUrl) { +// return FileManager.defaultManager.fileExists(await bookmarkUrl.path()); +// } +// +// return false; +// } +// +// @override +// Future lastModified() async { +// final URL? bookmarkUrl = await _bookmarkUrl; +// if (bookmarkUrl case URL bookmarkUrl) { +// final int? lastModifiedSinceEpoch = await FileManager.defaultManager +// .fileModificationDate(await bookmarkUrl.path()); +// if (lastModifiedSinceEpoch case int lastModifiedSinceEpoch) { +// return DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch); +// } +// } +// +// throw UnsupportedError('cant read: ${params.path}'); +// } +// +// @override +// Future length() async { +// final URL? bookmarkUrl = await _bookmarkUrl; +// if (bookmarkUrl case URL bookmarkUrl) { +// final int? fileSize = await FileManager.defaultManager.fileSize( +// await bookmarkUrl.path(), +// ); +// if (fileSize case int fileSize) { +// return fileSize; +// } +// } +// +// throw UnsupportedError('cant read: ${params.path}'); +// } +// +// @override +// Future delete() { +// // TODO: implement delete +// throw UnimplementedError(); +// } +// +// @override +// Stream> openRead([int? start, int? end]) async* { +// if (await _bookmarkUrl case URL url) { +// final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); +// try { +// Uint8List? bytes = await fileHandle.readUpToCount(4 * 1024); +// while (bytes != null && bytes.isNotEmpty) { +// yield bytes; +// // TODO: this is only supported on ios 13.4 +// bytes = await fileHandle.readUpToCount(4 * 1024); +// } +// } finally { +// await fileHandle.close(); +// } +// } else { +// throw UnsupportedError('Cant access bytes to file: ${params.path}'); +// } +// } +// +// @override +// Future readAsBytes() async { +// if (await _bookmarkUrl case URL url) { +// final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); +// try { +// final Uint8List? bytes = await fileHandle.readToEnd(); +// +// if (bytes case Uint8List bytes) { +// return bytes; +// } +// } finally { +// await fileHandle.close(); +// } +// } +// +// throw UnsupportedError('Cant access bytes to file: ${params.path}'); +// } +// +// @override +// Future readAsString({Encoding encoding = utf8}) async { +// return encoding.decode(await readAsBytes()); +// } +// } diff --git a/packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart b/packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart deleted file mode 100644 index fce69ec2e774..000000000000 --- a/packages/cross_file/cross_file_darwin/test/cross_file_darwin_method_channel_test.dart +++ /dev/null @@ -1,26 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_darwin/cross_file_darwin_method_channel.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - MethodChannelCrossFileDarwin platform = MethodChannelCrossFileDarwin(); - const MethodChannel channel = MethodChannel('cross_file_darwin'); - - setUp(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(channel, (MethodCall methodCall) async { - return '42'; - }); - }); - - tearDown(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .setMockMethodCallHandler(channel, null); - }); - - test('getPlatformVersion', () async { - expect(await platform.getPlatformVersion(), '42'); - }); -} diff --git a/packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart b/packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart deleted file mode 100644 index ef7f36f8f9c8..000000000000 --- a/packages/cross_file/cross_file_darwin/test/cross_file_darwin_test.dart +++ /dev/null @@ -1,28 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_darwin/cross_file_darwin.dart'; -import 'package:cross_file_darwin/cross_file_darwin_platform_interface.dart'; -import 'package:cross_file_darwin/cross_file_darwin_method_channel.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -class MockCrossFileDarwinPlatform - with MockPlatformInterfaceMixin - implements CrossFileDarwinPlatform { - @override - Future getPlatformVersion() => Future.value('42'); -} - -void main() { - final CrossFileDarwinPlatform initialPlatform = CrossFileDarwinPlatform.instance; - - test('$MethodChannelCrossFileDarwin is the default instance', () { - expect(initialPlatform, isInstanceOf()); - }); - - test('getPlatformVersion', () async { - CrossFileDarwin crossFileDarwinPlugin = CrossFileDarwin(); - MockCrossFileDarwinPlatform fakePlatform = MockCrossFileDarwinPlatform(); - CrossFileDarwinPlatform.instance = fakePlatform; - - expect(await crossFileDarwinPlugin.getPlatformVersion(), '42'); - }); -} From 8b424e9175d66135560ac59fce292fc901160892 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 14 Jan 2026 19:50:00 -0500 Subject: [PATCH 080/398] ios impl and update others --- .../android_shared_storage_cross_file.dart | 2 +- .../Classes/CrossFileDarwinApis.g.swift | 746 ++++++++++++++++ .../ios/Runner.xcodeproj/project.pbxproj | 112 +++ .../contents.xcworkspacedata | 3 + .../lib/src/cross_file_darwin_apis.g.dart | 800 ++++++++++++++++++ .../src/darwin_shared_storage_cross_file.dart | 419 +++++---- .../cross_file_darwin/pigeons/copyright.txt | 3 + .../pigeons/cross_file_darwin_apis.dart | 40 + .../lib/src/web_cross_file.dart | 2 +- 9 files changed, 1951 insertions(+), 176 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift create mode 100644 packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart create mode 100644 packages/cross_file/cross_file_darwin/pigeons/copyright.txt create mode 100644 packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart index 35d0a9e7a246..c596c9b4b867 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart @@ -77,7 +77,7 @@ base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { @override Future readAsString({Encoding encoding = utf8}) async { - return utf8.decode(await readAsBytes()); + return utf8.decodeStream(openRead()); } @override diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift new file mode 100644 index 000000000000..af067d08201e --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -0,0 +1,746 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.1.5), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func createConnectionError(withChannelName channelName: String) -> PigeonError { + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +/// Handles the callback when an object is deallocated. +protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { + /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. + func onDeinit(identifier: Int64) +} + + +// Attaches to an object to receive a callback when the object is deallocated. +internal final class CrossFileDarwinApisPigeonInternalFinalizer { + internal static let associatedObjectKey = malloc(1)! + + private let identifier: Int64 + // Reference to the delegate is weak because the callback should be ignored if the + // `InstanceManager` is deallocated. + internal weak var delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate? + + private init(identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { + self.identifier = identifier + self.delegate = delegate + } + + internal static func attach( + to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + ) { + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) + } + + static func detach(from instance: AnyObject) { + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + if let finalizer = finalizer { + finalizer.delegate = nil + objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) + } + } + + deinit { + delegate?.onDeinit(identifier: identifier) + } +} + + +/// Maintains instances used to communicate with the corresponding objects in Dart. +/// +/// Objects stored in this container are represented by an object in Dart that is also stored in +/// an InstanceManager with the same identifier. +/// +/// When an instance is added with an identifier, either can be used to retrieve the other. +/// +/// Added instances are added as a weak reference and a strong reference. When the strong +/// reference is removed and the weak reference is deallocated,`CrossFileDarwinApisPigeonInternalFinalizerDelegate.onDeinit` +/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is +/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), +/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually +/// again. +/// +/// Accessing and inserting to an InstanceManager is thread safe. +final class CrossFileDarwinApisPigeonInstanceManager { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private static let minHostCreatedIdentifier: Int64 = 65536 + + private let lockQueue = DispatchQueue(label: "CrossFileDarwinApisPigeonInstanceManager") + private let identifiers: NSMapTable = NSMapTable( + keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) + private let weakInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) + private let strongInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) + private let finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + private var nextIdentifier: Int64 = minHostCreatedIdentifier + + public init(finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { + self.finalizerDelegate = finalizerDelegate + } + + /// Adds a new instance that was instantiated from Dart. + /// + /// The same instance can be added multiple times, but each identifier must be unique. This allows + /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. + /// + /// - Parameters: + /// - instance: the instance to be stored + /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique + func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + lockQueue.async { + self.addInstance(instance, withIdentifier: identifier) + } + } + + /// Adds a new instance that was instantiated from the host platform. + /// + /// - Parameters: + /// - instance: the instance to be stored. This must be unique to all other added instances. + /// - Returns: the unique identifier (>= 0) stored with instance + func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { + assert(!containsInstance(instance), "Instance of \(instance) has already been added.") + var identifier: Int64 = -1 + lockQueue.sync { + identifier = nextIdentifier + nextIdentifier += 1 + self.addInstance(instance, withIdentifier: identifier) + } + return identifier + } + + /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier paired to an instance. + /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if + /// the manager doesn't contain the value + func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) + strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + /// Retrieves the instance associated with identifier. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier associated with an instance + /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func instance(forIdentifier instanceIdentifier: Int64) -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + assert(identifier >= 0) + assert( + weakInstances.object(forKey: identifier as NSNumber) == nil, + "Identifier has already been added: \(identifier)") + identifiers.setObject(NSNumber(value: identifier), forKey: instance) + weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) + strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) + CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + } + + /// Retrieves the identifier paired with an instance. + /// + /// If the manager contains a strong reference to `instance`, it will return the identifier + /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new + /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. + /// + /// If this method returns a nonnull identifier, this method also expects the Dart + /// `CrossFileDarwinApisPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + /// identifier is associated with. + /// + /// - Parameters: + /// - instance: an instance that may be stored in the manager + /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { + var identifier: Int64? = nil + lockQueue.sync { + if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { + strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) + identifier = existingIdentifier + } + } + return identifier + } + + /// Whether this manager contains the given `instance`. + /// + /// - Parameters: + /// - instance: the instance whose presence in this manager is to be tested + /// - Returns: whether this manager contains the given `instance` + func containsInstance(_ instance: AnyObject) -> Bool { + var containsInstance = false + lockQueue.sync { + containsInstance = identifiers.object(forKey: instance) != nil + } + return containsInstance + } + + /// Removes all of the instances from this manager. + /// + /// The manager will be empty after this call returns. + func removeAllObjects() throws { + lockQueue.sync { + let weakInstancesEnumerator = weakInstances.objectEnumerator()! + while let instance = weakInstancesEnumerator.nextObject() { + CrossFileDarwinApisPigeonInternalFinalizer.detach(from: instance as AnyObject) + } + identifiers.removeAllObjects() + weakInstances.removeAllObjects() + strongInstances.removeAllObjects() + nextIdentifier = CrossFileDarwinApisPigeonInstanceManager.minHostCreatedIdentifier + } + } + + /// The number of instances stored as a strong reference. + /// + /// For debugging and testing purposes. + internal var strongInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = strongInstances.count + } + return count + } + + /// The number of instances stored as a weak reference. + /// + /// For debugging and testing purposes. NSMapTables that store keys or objects as weak + /// reference will be reclaimed non-deterministically. + internal var weakInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = weakInstances.count + } + return count + } +} + + +private class CrossFileDarwinApisPigeonInstanceManagerApi { + /// The codec used for serializing messages. + var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } + + /// Handles sending and receiving messages with Dart. + unowned let binaryMessenger: FlutterBinaryMessenger + + init(binaryMessenger: FlutterBinaryMessenger) { + self.binaryMessenger = binaryMessenger + } + + /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + let codec = CrossFileDarwinApisPigeonCodec.shared + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + removeStrongReferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! Int64 + do { + let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeStrongReferenceChannel.setMessageHandler(nil) + } + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + clearChannel.setMessageHandler { _, reply in + do { + try instanceManager.removeAllObjects() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearChannel.setMessageHandler(nil) + } + } + + /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([identifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } +} +protocol CrossFileDarwinApisPigeonProxyApiDelegate { + /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of + /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle +} + +open class CrossFileDarwinApisPigeonProxyApiRegistrar { + let binaryMessenger: FlutterBinaryMessenger + let apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + let instanceManager: CrossFileDarwinApisPigeonInstanceManager + /// Whether APIs should ignore calling to Dart. + public var ignoreCallsToDart = false + private var _codec: FlutterStandardMessageCodec? + var codec: FlutterStandardMessageCodec { + if _codec == nil { + _codec = FlutterStandardMessageCodec( + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + } + return _codec! + } + + private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + let api: CrossFileDarwinApisPigeonInstanceManagerApi + + init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { + self.api = api + } + + public func onDeinit(identifier: Int64) { + api.removeStrongReference(identifier: identifier) { + _ in + } + } + } + + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + self.binaryMessenger = binaryMessenger + self.apiDelegate = apiDelegate + self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( + finalizerDelegate: InstanceManagerApiFinalizerDelegate( + CrossFileDarwinApisPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) + } + + func setUp() { + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + } + func tearDown() { + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + } +} +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + let identifier = self.readValue() + let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( + forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) + if instance == nil { + print("Failed to find instance with identifier: \(identifier!)") + } + return instance + default: + return super.readValue(ofType: type) + } + } + } + + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func writeValue(_ value: Any) { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + super.writeValue(value) + return + } + + + if let instance = value as? FileHandle { + pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + { + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) + } else { + print("Unsupported value: \(value) of \(type(of: value))") + assert(false, "Unsupported value for CrossFileDarwinApisPigeonInternalProxyApiCodecWriter") + } + + } + } + + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + } + + override func reader(with data: Data) -> FlutterStandardReader { + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + } +} + +private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { +} + +private class CrossFileDarwinApisPigeonCodecWriter: FlutterStandardWriter { +} + +private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return CrossFileDarwinApisPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return CrossFileDarwinApisPigeonCodecWriter(data: data) + } +} + +class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) +} + +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol CrossFileDarwinApi { + func tryCreateBookmarkedUrl(url: String) throws -> String? + func isReadableFile(url: String) throws -> Bool + func fileExists(url: String) throws -> Bool + func fileModificationDate(url: String) throws -> Int64? + func fileSize(url: String) throws -> Int64? +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class CrossFileDarwinApiSetup { + static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } + /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.tryCreateBookmarkedUrl(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + tryCreateBookmarkedUrlChannel.setMessageHandler(nil) + } + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isReadableFileChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.isReadableFile(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isReadableFileChannel.setMessageHandler(nil) + } + let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileExistsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileExists(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileExistsChannel.setMessageHandler(nil) + } + let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileModificationDateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileModificationDate(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileModificationDateChannel.setMessageHandler(nil) + } + let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileSizeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileSize(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileSizeChannel.setMessageHandler(nil) + } + } +} +protocol PigeonApiDelegateFileHandle { + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? + func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws -> Int64 + func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws +} + +protocol PigeonApiProtocolFileHandle { +} + +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateFileHandle + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let forReadingFromUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + forReadingFromUrlChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonIdentifierArg = args[0] as! Int64 + let urlArg = args[1] as! String + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( +try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), +withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + forReadingFromUrlChannel.setMessageHandler(nil) + } + let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + readUpToCountChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + let countArg = args[1] as! Int64 + do { + let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + readUpToCountChannel.setMessageHandler(nil) + } + let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + readToEndChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + do { + let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + readToEndChannel.setMessageHandler(nil) + } + let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + seekChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + let offsetArg = args[1] as! Int64 + do { + let result = try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + seekChannel.setMessageHandler(nil) + } + let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + closeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + do { + try api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + closeChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + } +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index d022f0831794..6b7b7966ab19 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -7,11 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 0BBE3A77F94E5BCEF9021C5A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; + 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -43,6 +45,9 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 26C8F5E7A3000CE8EAEBCE2D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; @@ -50,6 +55,8 @@ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -57,6 +64,9 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9D1864A39D740B0EAEC60CD5 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + B8A1290F753E9B94CB42B68A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +74,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0BBE3A77F94E5BCEF9021C5A /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + B320E567E4FD783B390DDCB2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -78,6 +97,15 @@ path = RunnerTests; sourceTree = ""; }; + 6F98F75533BE3213F9C0BF8F /* Frameworks */ = { + isa = PBXGroup; + children = ( + BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */, + 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -96,6 +124,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + DB75EE80F48401E65664EBB7 /* Pods */, + 6F98F75533BE3213F9C0BF8F /* Frameworks */, ); sourceTree = ""; }; @@ -124,6 +154,20 @@ path = Runner; sourceTree = ""; }; + DB75EE80F48401E65664EBB7 /* Pods */ = { + isa = PBXGroup; + children = ( + B8A1290F753E9B94CB42B68A /* Pods-Runner.debug.xcconfig */, + 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */, + 26C8F5E7A3000CE8EAEBCE2D /* Pods-Runner.profile.xcconfig */, + 9D1864A39D740B0EAEC60CD5 /* Pods-RunnerTests.debug.xcconfig */, + 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */, + 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -131,8 +175,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + B10C59BD6BC2E3B30B458863 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + B320E567E4FD783B390DDCB2 /* Frameworks */, ); buildRules = ( ); @@ -148,12 +194,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + E0527587EB0D03F15D75982F /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9CD0C6A1D95F083343210EC4 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -256,6 +304,67 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + 9CD0C6A1D95F083343210EC4 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + B10C59BD6BC2E3B30B458863 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E0527587EB0D03F15D75982F /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -383,6 +492,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 9D1864A39D740B0EAEC60CD5 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -400,6 +510,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -415,6 +526,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart new file mode 100644 index 000000000000..c9772a5bedd8 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -0,0 +1,800 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.1.5), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers + +import 'dart:async'; +import 'dart:io' show Platform; +import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; + +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; + +PlatformException _createConnectionError(String channelName) { + return PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); +} + +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} +/// Provides overrides for the constructors and static members of each +/// Dart proxy class. +/// +/// This is only intended to be used with unit tests to prevent errors from +/// making message calls in a unit test. +/// +/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. +@visibleForTesting +class PigeonOverrides { + /// Overrides [FileHandle.forReadingFromUrl]. + static FileHandle Function({required String url})? + fileHandle_forReadingFromUrl; + + /// Sets all overridden ProxyApi class members to null. + static void pigeon_reset() { + fileHandle_forReadingFromUrl = null; + } +} + +/// An immutable object that serves as the base class for all Dart proxy classes +/// and can provide functional copies of itself. +/// +/// All implementers are expected to be [immutable] as defined by the annotation +/// and override [pigeon_copy] returning an instance of itself. +@immutable +abstract class PigeonInternalProxyApiBaseClass { + /// Construct a [PigeonInternalProxyApiBaseClass]. + PigeonInternalProxyApiBaseClass({ + this.pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) : pigeon_instanceManager = + pigeon_instanceManager ?? PigeonInstanceManager.instance; + + /// Sends and receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used, which routes to + /// the host platform. + @protected + final BinaryMessenger? pigeon_binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final PigeonInstanceManager pigeon_instanceManager; + + /// Instantiates and returns a functionally identical object to oneself. + /// + /// Outside of tests, this method should only ever be called by + /// [PigeonInstanceManager]. + /// + /// Subclasses should always override their parent's implementation of this + /// method. + @protected + PigeonInternalProxyApiBaseClass pigeon_copy(); +} + +/// Maintains instances used to communicate with the native objects they +/// represent. +/// +/// Added instances are stored as weak references and their copies are stored +/// as strong references to maintain access to their variables and callback +/// methods. Both are stored with the same identifier. +/// +/// When a weak referenced instance becomes inaccessible, +/// [onWeakReferenceRemoved] is called with its associated identifier. +/// +/// If an instance is retrieved and has the possibility to be used, +/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference +/// is added as a weak reference with the same identifier. This prevents a +/// scenario where the weak referenced instance was released and then later +/// returned by the host platform. +class PigeonInstanceManager { + /// Constructs a [PigeonInstanceManager]. + PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { + this.onWeakReferenceRemoved = (int identifier) { + _weakInstances.remove(identifier); + onWeakReferenceRemoved(identifier); + }; + _finalizer = Finalizer(this.onWeakReferenceRemoved); + } + + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously by the host platform. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + static const int _maxDartCreatedIdentifier = 65536; + + /// The default [PigeonInstanceManager] used by Dart proxy classes. + /// + /// On creation, this manager makes a call to clear the native + /// InstanceManager. This is to prevent identifier conflicts after a host + /// restart. + static final PigeonInstanceManager instance = _initInstance(); + + // Expando is used because it doesn't prevent its keys from becoming + // inaccessible. This allows the manager to efficiently retrieve an identifier + // of an instance without holding a strong reference to that instance. + // + // It also doesn't use `==` to search for identifiers, which would lead to an + // infinite loop when comparing an object to its copy. (i.e. which was caused + // by calling instanceManager.getIdentifier() inside of `==` while this was a + // HashMap). + final Expando _identifiers = Expando(); + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; + late final Finalizer _finalizer; + int _nextIdentifier = 0; + + /// Called when a weak referenced instance is removed by [removeWeakReference] + /// or becomes inaccessible. + late final void Function(int) onWeakReferenceRemoved; + + static PigeonInstanceManager _initInstance() { + if (Platform.environment['FLUTTER_TEST'] == 'true') { + return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + } + WidgetsFlutterBinding.ensureInitialized(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. + api.clear(); + final PigeonInstanceManager instanceManager = PigeonInstanceManager( + onWeakReferenceRemoved: (int identifier) { + api.removeStrongReference(identifier); + }, + ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + return instanceManager; + } + + /// Adds a new instance that was instantiated by Dart. + /// + /// In other words, Dart wants to add a new instance that will represent + /// an object that will be instantiated on the host platform. + /// + /// Throws assertion error if the instance has already been added. + /// + /// Returns the randomly generated id of the [instance] added. + int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { + assert(getIdentifier(instance) == null); + + final int identifier = _nextUniqueIdentifier(); + _identifiers[instance] = identifier; + _weakInstances[identifier] = + WeakReference(instance); + _finalizer.attach(instance, identifier, detach: instance); + + final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); + _identifiers[copy] = identifier; + _strongInstances[identifier] = copy; + return identifier; + } + + /// Removes the instance, if present, and call [onWeakReferenceRemoved] with + /// its identifier. + /// + /// Returns the identifier associated with the removed instance. Otherwise, + /// `null` if the instance was not found in this manager. + /// + /// This does not remove the strong referenced instance associated with + /// [instance]. This can be done with [remove]. + int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { + final int? identifier = getIdentifier(instance); + if (identifier == null) { + return null; + } + + _identifiers[instance] = null; + _finalizer.detach(instance); + onWeakReferenceRemoved(identifier); + + return identifier; + } + + /// Removes [identifier] and its associated strongly referenced instance, if + /// present, from the manager. + /// + /// Returns the strong referenced instance associated with [identifier] before + /// it was removed. Returns `null` if [identifier] was not associated with + /// any strong reference. + /// + /// Throws an `AssertionError` if the weak referenced instance associated with + /// [identifier] is not removed first. This can be done with + /// [removeWeakReference]. + T? remove(int identifier) { + final T? instance = _weakInstances[identifier]?.target as T?; + assert( + instance == null, + 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', + ); + return _strongInstances.remove(identifier) as T?; + } + + /// Retrieves the instance associated with identifier. + /// + /// The value returned is chosen from the following order: + /// + /// 1. A weakly referenced instance associated with identifier. + /// 2. If the only instance associated with identifier is a strongly + /// referenced instance, a copy of the instance is added as a weak reference + /// with the same identifier. Returning the newly created copy. + /// 3. If no instance is associated with identifier, returns null. + /// + /// This method also expects the host `InstanceManager` to have a strong + /// reference to the instance the identifier is associated with. + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + + if (weakInstance == null) { + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + if (strongInstance != null) { + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + _identifiers[copy] = identifier; + _weakInstances[identifier] = WeakReference(copy); + _finalizer.attach(copy, identifier, detach: copy); + return copy as T; + } + return strongInstance as T?; + } + + return weakInstance as T; + } + + /// Retrieves the identifier associated with instance. + int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { + return _identifiers[instance]; + } + + /// Adds a new instance that was instantiated by the host platform. + /// + /// In other words, the host platform wants to add a new instance that + /// represents an object on the host platform. Stored with [identifier]. + /// + /// Throws assertion error if the instance or its identifier has already been + /// added. + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + assert(!containsIdentifier(identifier)); + assert(getIdentifier(instance) == null); + assert(identifier >= 0); + + _identifiers[instance] = identifier; + _strongInstances[identifier] = instance; + } + + /// Whether this manager contains the given [identifier]. + bool containsIdentifier(int identifier) { + return _weakInstances.containsKey(identifier) || + _strongInstances.containsKey(identifier); + } + + int _nextUniqueIdentifier() { + late int identifier; + do { + identifier = _nextIdentifier; + _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; + } while (containsIdentifier(identifier)); + return identifier; + } +} + +/// Generated API for managing the Dart and native `PigeonInstanceManager`s. +class _PigeonInternalInstanceManagerApi { + /// Constructor for [_PigeonInternalInstanceManagerApi]. + _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) + : pigeonVar_binaryMessenger = binaryMessenger; + + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + static void setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? binaryMessenger, + PigeonInstanceManager? instanceManager, + }) { + { + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.'); + final List args = (message as List?)!; + final int? arg_identifier = (args[0] as int?); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + try { + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future removeStrongReference(int identifier) async { + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + /// Clear the native `PigeonInstanceManager`. + /// + /// This is typically called after a hot restart. + Future clear() async { + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } +} + +class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} + + + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +class CrossFileDarwinApi { + /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + final String pigeonVar_messageChannelSuffix; + + Future tryCreateBookmarkedUrl(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as String?); + } + } + + Future isReadableFile(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future fileExists(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + Future fileModificationDate(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as int?); + } + } + + Future fileSize(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as int?); + } + } +} +class FileHandle extends PigeonInternalProxyApiBaseClass { + factory FileHandle.forReadingFromUrl({ + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + required String url, + }) { + if (PigeonOverrides.fileHandle_forReadingFromUrl != null) { + return PigeonOverrides.fileHandle_forReadingFromUrl!(url: url); + } + return FileHandle.pigeon_forReadingFromUrl( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + url: url, + ); + } + + @protected + FileHandle.pigeon_forReadingFromUrl({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required String url, + }) { + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier, url]); + () async { + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + } + + /// Constructs [FileHandle] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + FileHandle.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileHandle = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + FileHandle Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + FileHandle.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future readUpToCount(int count) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, count]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as Uint8List?); + } + } + + Future readToEnd() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as Uint8List?); + } + } + + Future seek(int offset) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.seek'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, offset]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as int?)!; + } + } + + Future close() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecFileHandle; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.close'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + @override + FileHandle pigeon_copy() { + return FileHandle.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} + diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart index 515d19990d07..c223e260562b 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart @@ -1,174 +1,245 @@ -// // Copyright 2013 The Flutter Authors -// // Use of this source code is governed by a BSD-style license that can be -// // found in the LICENSE file. -// -// import 'dart:convert'; -// import 'dart:typed_data'; -// -// import 'package:cross_file_ios/src/foundation.g.dart'; -// import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -// import 'package:flutter/foundation.dart'; -// -// /// Implementation of [PlatformXFileCreationParams] for iOS and macOS. -// @immutable -// base class DarwinXFileCreationParams extends PlatformXFileCreationParams { -// /// Constructs a [DarwinXFileCreationParams]. -// const DarwinXFileCreationParams({required super.uri}) : super(); -// } -// -// // Note for me: Will probs need a `static Future method(Uint8List bookmarkData` method -// // instead to create persistent file. -// base class IOSXFile extends PlatformSharedStorageXFile { -// IOSXFile(super.params) : super.implementation(); -// -// Future asBookmarkedFile() { -// final URL? url = await _originalUrl; -// if (url case URL url) { -// final bool canRead = await url.startAccessingSecurityScopedResource(); -// if (canRead) { -// try { -// final Uint8List? bookmarkData = await url.bookmarkData([], [], null); -// if (bookmarkData case Uint8List bookmarkData) { -// final URLResolvingBookmarkDataResponse response = await URL -// .resolvingBookmarkData(bookmarkData, [], null); -// if (response.isStale) { -// print('STALE'); -// return null; -// } -// return response.url; -// } -// } finally { -// await url.stopAccessingSecurityScopedResource(); -// } -// } -// } -// -// return null; -// } -// -// late final Future _originalUrl = URL.fileURLWithPath(params.path); -// -// late final Future _bookmarkUrl = () async { -// final URL? url = await _originalUrl; -// if (url case URL url) { -// final bool canRead = await url.startAccessingSecurityScopedResource(); -// if (canRead) { -// try { -// final Uint8List? bookmarkData = await url.bookmarkData([], [], null); -// if (bookmarkData case Uint8List bookmarkData) { -// final URLResolvingBookmarkDataResponse response = await URL -// .resolvingBookmarkData(bookmarkData, [], null); -// if (response.isStale) { -// print('STALE'); -// return null; -// } -// return response.url; -// } -// } finally { -// await url.stopAccessingSecurityScopedResource(); -// } -// } -// } -// -// return null; -// }(); -// -// @override -// Future canRead() async { -// final URL? bookmarkUrl = await _bookmarkUrl; -// if (bookmarkUrl case URL bookmarkUrl) { -// return FileManager.defaultManager.isReadableFile( -// await bookmarkUrl.path(), -// ); -// } -// -// return false; -// } -// -// @override -// Future exists() async { -// final URL? bookmarkUrl = await _bookmarkUrl; -// if (bookmarkUrl case URL bookmarkUrl) { -// return FileManager.defaultManager.fileExists(await bookmarkUrl.path()); -// } -// -// return false; -// } -// -// @override -// Future lastModified() async { -// final URL? bookmarkUrl = await _bookmarkUrl; -// if (bookmarkUrl case URL bookmarkUrl) { -// final int? lastModifiedSinceEpoch = await FileManager.defaultManager -// .fileModificationDate(await bookmarkUrl.path()); -// if (lastModifiedSinceEpoch case int lastModifiedSinceEpoch) { -// return DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch); -// } -// } -// -// throw UnsupportedError('cant read: ${params.path}'); -// } -// -// @override -// Future length() async { -// final URL? bookmarkUrl = await _bookmarkUrl; -// if (bookmarkUrl case URL bookmarkUrl) { -// final int? fileSize = await FileManager.defaultManager.fileSize( -// await bookmarkUrl.path(), -// ); -// if (fileSize case int fileSize) { -// return fileSize; -// } -// } -// -// throw UnsupportedError('cant read: ${params.path}'); -// } -// -// @override -// Future delete() { -// // TODO: implement delete -// throw UnimplementedError(); -// } -// -// @override -// Stream> openRead([int? start, int? end]) async* { -// if (await _bookmarkUrl case URL url) { -// final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); -// try { -// Uint8List? bytes = await fileHandle.readUpToCount(4 * 1024); -// while (bytes != null && bytes.isNotEmpty) { -// yield bytes; -// // TODO: this is only supported on ios 13.4 -// bytes = await fileHandle.readUpToCount(4 * 1024); -// } -// } finally { -// await fileHandle.close(); -// } -// } else { -// throw UnsupportedError('Cant access bytes to file: ${params.path}'); -// } -// } -// -// @override -// Future readAsBytes() async { -// if (await _bookmarkUrl case URL url) { -// final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); -// try { -// final Uint8List? bytes = await fileHandle.readToEnd(); -// -// if (bytes case Uint8List bytes) { -// return bytes; -// } -// } finally { -// await fileHandle.close(); -// } -// } -// -// throw UnsupportedError('Cant access bytes to file: ${params.path}'); -// } -// -// @override -// Future readAsString({Encoding encoding = utf8}) async { -// return encoding.decode(await readAsBytes()); -// } -// } +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:math'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; + +import 'cross_file_darwin_apis.g.dart'; + +/// Implementation of [PlatformSharedStorageXFileCreationParams] for iOS and +/// macOS. +@immutable +base class DarwinSharedStorageXFileCreationParams + extends PlatformSharedStorageXFileCreationParams { + /// Constructs a [DarwinSharedStorageXFileCreationParams]. + DarwinSharedStorageXFileCreationParams({ + required super.uri, + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(); + + @visibleForTesting + final CrossFileDarwinApi api; +} + +/// Implementation of [PlatformSharedStorageXFile] for iOS and macOS. +base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { + /// Constructs a [DarwinSharedStorageXFile]. + DarwinSharedStorageXFile(super.params) : super.implementation(); + + /// Maximum number of bytes to read at a time from the native Android + /// InputStream. + /// + /// Only visible for testing. + @visibleForTesting + static const int maxByteArrayLen = 4 * 1024; + + @override + late final DarwinSharedStorageXFileCreationParams params = + super.params is DarwinSharedStorageXFileCreationParams + ? super.params as DarwinSharedStorageXFileCreationParams + : DarwinSharedStorageXFileCreationParams(uri: params.uri); + + Future toBookmarkedFile() async { + final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( + params.uri, + ); + + return bookmarkedUrl != null + ? DarwinSharedStorageXFileCreationParams(uri: bookmarkedUrl) + : null; + // final URL? url = await _originalUrl; + // if (url case URL url) { + // final bool canRead = await url.startAccessingSecurityScopedResource(); + // if (canRead) { + // try { + // final Uint8List? bookmarkData = await url.bookmarkData([], [], null); + // if (bookmarkData case Uint8List bookmarkData) { + // final URLResolvingBookmarkDataResponse response = await URL + // .resolvingBookmarkData(bookmarkData, [], null); + // if (response.isStale) { + // print('STALE'); + // return null; + // } + // return response.url; + // } + // } finally { + // await url.stopAccessingSecurityScopedResource(); + // } + // } + } + + @override + Future canRead() => params.api.isReadableFile(params.uri); + + @override + Future exists() => params.api.fileExists(params.uri); + + @override + Future lastModified() async { + final int? lastModifiedSinceEpoch = await params.api.fileModificationDate( + params.uri, + ); + return lastModifiedSinceEpoch != null + ? DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch) + : throw UnsupportedError(''); + } + + @override + Future length() async => await params.api.fileSize(params.uri) ?? 0; + + @override + Future name() { + throw UnimplementedError(); + } + + @override + Stream openRead([int? start, int? end]) async* { + int bytesToRead = (end ?? await length()) - (start ?? 0); + assert(bytesToRead >= 0); + + final handle = FileHandle.forReadingFromUrl(url: params.uri); + try { + if (start != null && start > 0) { + await handle.seek(start); + } + + do { + final Uint8List? bytes = await handle.readUpToCount( + min(bytesToRead, maxByteArrayLen), + ); + + if (bytes == null) { + throw StateError('Failed to read bytes from file: ${params.uri}'); + } else { + yield bytes; + } + + bytesToRead -= bytes.length; + } while (bytesToRead > 0); + } finally { + await handle.close(); + } + } + + @override + Future readAsBytes() async { + final handle = FileHandle.forReadingFromUrl(url: params.uri); + try { + final Uint8List? bytes = await handle.readToEnd(); + if (bytes == null) { + throw StateError('Failed to read bytes from file: ${params.uri}'); + } + + return bytes; + } finally { + await handle.close(); + } + } + + @override + Future readAsString({Encoding encoding = utf8}) async { + return utf8.decodeStream(openRead()); + } + + // late final Future _originalUrl = URL.fileURLWithPath(params.path); + // + // late final Future _bookmarkUrl = () async { + // final URL? url = await _originalUrl; + // if (url case URL url) { + // final bool canRead = await url.startAccessingSecurityScopedResource(); + // if (canRead) { + // try { + // final Uint8List? bookmarkData = await url.bookmarkData([], [], null); + // if (bookmarkData case Uint8List bookmarkData) { + // final URLResolvingBookmarkDataResponse response = await URL + // .resolvingBookmarkData(bookmarkData, [], null); + // if (response.isStale) { + // print('STALE'); + // return null; + // } + // return response.url; + // } + // } finally { + // await url.stopAccessingSecurityScopedResource(); + // } + // } + // } + // + // return null; + // }(); + // + // @override + // Future canRead() async { + // final URL? bookmarkUrl = await _bookmarkUrl; + // if (bookmarkUrl case URL bookmarkUrl) { + // return FileManager.defaultManager.isReadableFile( + // await bookmarkUrl.path(), + // ); + // } + // + // return false; + // } + // + // @override + // Future exists() async { + // final URL? bookmarkUrl = await _bookmarkUrl; + // if (bookmarkUrl case URL bookmarkUrl) { + // return FileManager.defaultManager.fileExists(await bookmarkUrl.path()); + // } + // + // return false; + // } + // + // @override + // Future lastModified() async { + // final URL? bookmarkUrl = await _bookmarkUrl; + // if (bookmarkUrl case URL bookmarkUrl) { + // final int? lastModifiedSinceEpoch = await FileManager.defaultManager + // .fileModificationDate(await bookmarkUrl.path()); + // if (lastModifiedSinceEpoch case int lastModifiedSinceEpoch) { + // return DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch); + // } + // } + // + // throw UnsupportedError('cant read: ${params.path}'); + // } + // + // @override + // Future length() async { + // final URL? bookmarkUrl = await _bookmarkUrl; + // if (bookmarkUrl case URL bookmarkUrl) { + // final int? fileSize = await FileManager.defaultManager.fileSize( + // await bookmarkUrl.path(), + // ); + // if (fileSize case int fileSize) { + // return fileSize; + // } + // } + // + // throw UnsupportedError('cant read: ${params.path}'); + // } + + // @override + // Stream> openRead([int? start, int? end]) async* { + // if (await _bookmarkUrl case URL url) { + // final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); + // try { + // Uint8List? bytes = await fileHandle.readUpToCount(4 * 1024); + // while (bytes != null && bytes.isNotEmpty) { + // yield bytes; + // // TODO: this is only supported on ios 13.4 + // bytes = await fileHandle.readUpToCount(4 * 1024); + // } + // } finally { + // await fileHandle.close(); + // } + // } else { + // throw UnsupportedError('Cant access bytes to file: ${params.path}'); + // } + // } +} diff --git a/packages/cross_file/cross_file_darwin/pigeons/copyright.txt b/packages/cross_file/cross_file_darwin/pigeons/copyright.txt new file mode 100644 index 000000000000..07e5f8598a80 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/pigeons/copyright.txt @@ -0,0 +1,3 @@ +Copyright 2013 The Flutter Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart new file mode 100644 index 000000000000..ef3b3b3200de --- /dev/null +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -0,0 +1,40 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_unused_constructor_parameters + +import 'package:pigeon/pigeon.dart'; + +@ConfigurePigeon( + PigeonOptions( + dartOut: 'lib/src/cross_file_darwin_apis.g.dart', + swiftOut: 'darwin/Classes/CrossFileDarwinApis.g.swift', + copyrightHeader: 'pigeons/copyright.txt', + ), +) +@HostApi() +abstract class CrossFileDarwinApi { + String? tryCreateBookmarkedUrl(String url); + + bool isReadableFile(String url); + + bool fileExists(String url); + + int? fileModificationDate(String url); + + int? fileSize(String url); +} + +@ProxyApi() +abstract class FileHandle { + FileHandle.forReadingFromUrl(String url); + + Uint8List? readUpToCount(int count); + + Uint8List? readToEnd(); + + int seek(int offset); + + void close(); +} diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index 06d4ba1614a9..7eb3ed52c717 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -123,7 +123,7 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { @override Future readAsString({Encoding encoding = utf8}) async { - return encoding.decode(await readAsBytes()); + return encoding.decodeStream(openRead()); } @override From 608d9fd32b6c5866987c9bd01389a21c54265221 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:00:06 -0500 Subject: [PATCH 081/398] change to scoped storage --- .../lib/cross_file_platform_interface.dart | 4 +- .../lib/src/cross_file_platform.dart | 20 +++---- ...tform_scoped_storage_cross_directory.dart} | 58 +++++++++---------- .../platform_scoped_storage_cross_file.dart} | 58 +++++++++---------- 4 files changed, 70 insertions(+), 70 deletions(-) rename packages/cross_file/cross_file_platform_interface/lib/src/{shared_storage/platform_shared_storage_cross_directory.dart => scoped_storage/platform_scoped_storage_cross_directory.dart} (56%) rename packages/cross_file/cross_file_platform_interface/lib/src/{shared_storage/platform_shared_storage_cross_file.dart => scoped_storage/platform_scoped_storage_cross_file.dart} (56%) diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index c825aff5fbd4..11ff1f582661 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -6,5 +6,5 @@ export 'src/cross_file_platform.dart'; export 'src/platform_cross_directory.dart'; export 'src/platform_cross_file.dart'; export 'src/platform_cross_file_entity.dart'; -export 'src/shared_storage/platform_shared_storage_cross_directory.dart'; -export 'src/shared_storage/platform_shared_storage_cross_file.dart'; +export 'src/scoped_storage/platform_scoped_storage_cross_directory.dart'; +export 'src/scoped_storage/platform_scoped_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 979c05e83e9c..bfb4edabd0b5 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -6,8 +6,8 @@ import 'package:flutter/foundation.dart'; import 'platform_cross_directory.dart'; import 'platform_cross_file.dart'; -import 'shared_storage/platform_shared_storage_cross_directory.dart'; -import 'shared_storage/platform_shared_storage_cross_file.dart'; +import 'scoped_storage/platform_scoped_storage_cross_directory.dart'; +import 'scoped_storage/platform_scoped_storage_cross_file.dart'; /// Interface for a platform implementation of `cross_file`. abstract base class CrossFilePlatform { @@ -30,21 +30,21 @@ abstract base class CrossFilePlatform { ); } - /// Creates a new [PlatformSharedStorageXDirectory]. - PlatformSharedStorageXFile createPlatformSharedStorageXFile( - PlatformSharedStorageXFileCreationParams params, + /// Creates a new [PlatformScopedStorageXDirectory]. + PlatformScopedStorageXFile createPlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, ) { throw UnimplementedError( - 'createPlatformSharedStorageXFile is not implemented on the current platform.', + 'createPlatformScopedStorageXFile is not implemented on the current platform.', ); } - /// Creates a new [PlatformSharedStorageXDirectory]. - PlatformSharedStorageXDirectory createPlatformSharedStorageXDirectory( - PlatformSharedStorageXDirectoryCreationParams params, + /// Creates a new [PlatformScopedStorageXDirectory]. + PlatformScopedStorageXDirectory createPlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams params, ) { throw UnimplementedError( - 'createPlatformSharedStorageXDirectory is not implemented on the current platform.', + 'createPlatformScopedStorageXDirectory is not implemented on the current platform.', ); } } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart similarity index 56% rename from packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart rename to packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index 9d9713f7f62a..0156289e5bea 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -7,28 +7,28 @@ import 'package:flutter/foundation.dart'; import '../cross_file_platform.dart'; import '../platform_cross_directory.dart'; -/// Object specifying creation parameters for creating a [PlatformSharedStorageXDirectory]. +/// Object specifying creation parameters for creating a [PlatformScopedStorageXDirectory]. /// /// Platform specific implementations can add additional fields by extending /// this class. /// -/// This example demonstrates how to extend the [PlatformSharedStorageXDirectoryCreationParams] to +/// This example demonstrates how to extend the [PlatformScopedStorageXDirectoryCreationParams] to /// provide additional platform specific parameters. /// -/// When extending [PlatformSharedStorageXDirectoryCreationParams] additional parameters +/// When extending [PlatformScopedStorageXDirectoryCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking /// changes. /// /// ```dart -/// base class AndroidSharedStorageXDirectoryCreationParams -/// extends PlatformSharedStorageXDirectoryCreationParams { -/// AndroidSharedStorageXDirectoryCreationParams({required super.uri, this.platformValue}); +/// base class AndroidScopedStorageXDirectoryCreationParams +/// extends PlatformScopedStorageXDirectoryCreationParams { +/// AndroidScopedStorageXDirectoryCreationParams({required super.uri, this.platformValue}); /// -/// factory AndroidSharedStorageXDirectoryCreationParams.fromCreationParams( -/// PlatformSharedStorageXDirectoryCreationParams params, { +/// factory AndroidScopedStorageXDirectoryCreationParams.fromCreationParams( +/// PlatformScopedStorageXDirectoryCreationParams params, { /// Object? platformValue, /// }) { -/// return AndroidSharedStorageXDirectoryCreationParams( +/// return AndroidScopedStorageXDirectoryCreationParams( /// uri: params.uri, /// platformValue: platformValue, /// ); @@ -38,42 +38,42 @@ import '../platform_cross_directory.dart'; /// } /// ``` @immutable -base class PlatformSharedStorageXDirectoryCreationParams +base class PlatformScopedStorageXDirectoryCreationParams extends PlatformXDirectoryCreationParams { - /// Constructs a [PlatformSharedStorageXDirectoryCreationParams]. - const PlatformSharedStorageXDirectoryCreationParams({required super.uri}); + /// Constructs a [PlatformScopedStorageXDirectoryCreationParams]. + const PlatformScopedStorageXDirectoryCreationParams({required super.uri}); } /// Base mixin used to provide platform specific features for implementations of -/// [PlatformSharedStorageXDirectory]. +/// [PlatformScopedStorageXDirectory]. /// /// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformSharedStorageXDirectory.extension]. +/// this mixin and return an instance with [PlatformScopedStorageXDirectory.extension]. /// /// ```dart -/// base class AndroidSharedStorageXDirectory extends PlatformSharedStorageXDirectory with AndroidXFileExtension { +/// base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirectory with AndroidXFileExtension { /// // ... /// @override -/// PlatformSharedStorageXDirectoryExtension? get extension => this; +/// PlatformScopedStorageXDirectoryExtension? get extension => this; /// /// Future platformMethod() { /// // ... /// } /// } /// -/// mixin AndroidXFileExtension implements PlatformSharedStorageXDirectoryExtension { +/// mixin AndroidXFileExtension implements PlatformScopedStorageXDirectoryExtension { /// Future platformMethod(); /// } /// ``` -mixin SharedStoragePlatformXDirectoryExtension +mixin ScopedStoragePlatformXDirectoryExtension implements PlatformXDirectoryExtension {} /// A reference to a directory (or folder) on the file system within a devices -/// shared storage. -abstract base class PlatformSharedStorageXDirectory extends PlatformXDirectory { - /// Creates a new [PlatformSharedStorageXDirectory] - factory PlatformSharedStorageXDirectory( - PlatformSharedStorageXDirectoryCreationParams params, +/// scoped storage. +abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { + /// Creates a new [PlatformScopedStorageXDirectory] + factory PlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams params, ) { assert( CrossFilePlatform.instance != null, @@ -82,21 +82,21 @@ abstract base class PlatformSharedStorageXDirectory extends PlatformXDirectory { '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); - return CrossFilePlatform.instance!.createPlatformSharedStorageXDirectory( + return CrossFilePlatform.instance!.createPlatformScopedStorageXDirectory( params, ); } /// Used by the platform implementation to create a new - /// [PlatformSharedStorageXDirectory]. + /// [PlatformScopedStorageXDirectory]. /// /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. - PlatformSharedStorageXDirectory.implementation( - PlatformSharedStorageXDirectoryCreationParams super.params, + PlatformScopedStorageXDirectory.implementation( + PlatformScopedStorageXDirectoryCreationParams super.params, ) : super.implementation(); @override - PlatformSharedStorageXDirectoryCreationParams get params => - super.params as PlatformSharedStorageXDirectoryCreationParams; + PlatformScopedStorageXDirectoryCreationParams get params => + super.params as PlatformScopedStorageXDirectoryCreationParams; } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart similarity index 56% rename from packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart rename to packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index 3840ab745448..85cb6fbfe063 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/shared_storage/platform_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -7,28 +7,28 @@ import 'package:flutter/foundation.dart'; import '../cross_file_platform.dart'; import '../platform_cross_file.dart'; -/// Object specifying creation parameters for creating a [PlatformSharedStorageXFile]. +/// Object specifying creation parameters for creating a [PlatformScopedStorageXFile]. /// /// Platform specific implementations can add additional fields by extending /// this class. /// -/// This example demonstrates how to extend the [PlatformSharedStorageXFileCreationParams] to +/// This example demonstrates how to extend the [PlatformScopedStorageXFileCreationParams] to /// provide additional platform specific parameters. /// -/// When extending [PlatformSharedStorageXFileCreationParams] additional parameters +/// When extending [PlatformScopedStorageXFileCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking /// changes. /// /// ```dart -/// base class AndroidSharedStorageXFileCreationParams -/// extends PlatformSharedStorageXFileCreationParams { -/// AndroidSharedStorageXFileCreationParams({required super.uri, this.platformValue}); +/// base class AndroidScopedStorageXFileCreationParams +/// extends PlatformScopedStorageXFileCreationParams { +/// AndroidScopedStorageXFileCreationParams({required super.uri, this.platformValue}); /// -/// factory AndroidSharedStorageXFileCreationParams.fromCreationParams( -/// PlatformSharedStorageXFileCreationParams params, { +/// factory AndroidScopedStorageXFileCreationParams.fromCreationParams( +/// PlatformScopedStorageXFileCreationParams params, { /// Object? platformValue, /// }) { -/// return AndroidSharedStorageXFileCreationParams( +/// return AndroidScopedStorageXFileCreationParams( /// uri: params.uri, /// platformValue: platformValue, /// ); @@ -38,41 +38,41 @@ import '../platform_cross_file.dart'; /// } /// ``` @immutable -base class PlatformSharedStorageXFileCreationParams +base class PlatformScopedStorageXFileCreationParams extends PlatformXFileCreationParams { - /// Constructs a [PlatformSharedStorageXFileCreationParams]. - const PlatformSharedStorageXFileCreationParams({required super.uri}); + /// Constructs a [PlatformScopedStorageXFileCreationParams]. + const PlatformScopedStorageXFileCreationParams({required super.uri}); } /// Base mixin used to provide platform specific features for implementations of -/// [PlatformSharedStorageXFile]. +/// [PlatformScopedStorageXFile]. /// /// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformSharedStorageXFile.extension]. +/// this mixin and return an instance with [PlatformScopedStorageXFile.extension]. /// /// ```dart -/// base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile with AndroidXFileExtension { +/// base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile with AndroidXFileExtension { /// // ... /// @override -/// PlatformSharedStorageXFileExtension? get extension => this; +/// PlatformScopedStorageXFileExtension? get extension => this; /// /// Future platformMethod() { /// // ... /// } /// } /// -/// mixin AndroidXFileExtension implements PlatformSharedStorageXFileExtension { +/// mixin AndroidXFileExtension implements PlatformScopedStorageXFileExtension { /// Future platformMethod(); /// } /// ``` -mixin PlatformSharedStorageXFileExtension implements PlatformXFileExtension {} +mixin PlatformScopedStorageXFileExtension implements PlatformXFileExtension {} /// Interface for a reference to a local data resource within a devices -/// shared storage. -abstract base class PlatformSharedStorageXFile extends PlatformXFile { - /// Creates a new [PlatformSharedStorageXFile] - factory PlatformSharedStorageXFile( - PlatformSharedStorageXFileCreationParams params, +/// scoped storage. +abstract base class PlatformScopedStorageXFile extends PlatformXFile { + /// Creates a new [PlatformScopedStorageXFile] + factory PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, ) { assert( CrossFilePlatform.instance != null, @@ -81,20 +81,20 @@ abstract base class PlatformSharedStorageXFile extends PlatformXFile { '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); - return CrossFilePlatform.instance!.createPlatformSharedStorageXFile(params); + return CrossFilePlatform.instance!.createPlatformScopedStorageXFile(params); } /// Used by the platform implementation to create a new - /// [PlatformSharedStorageXFile]. + /// [PlatformScopedStorageXFile]. /// /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformSharedStorageXFile.implementation( - PlatformSharedStorageXFileCreationParams super.params, + PlatformScopedStorageXFile.implementation( + PlatformScopedStorageXFileCreationParams super.params, ) : super.implementation(); @override - PlatformSharedStorageXFileCreationParams get params => - super.params as PlatformSharedStorageXFileCreationParams; + PlatformScopedStorageXFileCreationParams get params => + super.params as PlatformScopedStorageXFileCreationParams; } From b9ff1870e65c0676309e9ec6ed7704debb37c74f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:19:33 -0500 Subject: [PATCH 082/398] update docs --- .../lib/src/platform_cross_file.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 5703a83194fc..11288c15d8ee 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -97,13 +97,13 @@ abstract base class PlatformXFile extends PlatformXFileEntity { /// Date and time when the resource was last modified, if the information is /// available. /// - /// Platforms may throw an exception if the information is not available. - Future lastModified(); + /// Returns null if file doesn't exist or information is not available. + Future lastModified(); /// The length of the data represented by this uri, in bytes. /// - /// Platforms may throw an exception if the information is not available. - Future length(); + /// Returns null if file doesn't exist or information is not available. + Future length(); /// Whether the resource represented by this reference can be read. Future canRead(); @@ -135,5 +135,7 @@ abstract base class PlatformXFile extends PlatformXFileEntity { /// The name of the resource represented by this object. /// /// The path is excluded from this value. + /// + /// Returns null if file doesn't exist or information is not available. Future name(); } From cd34c7c3c38b2efd0e8e6049a7072bdffe3f8c9d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:36:32 -0500 Subject: [PATCH 083/398] return null on exception --- .../cross_file_io/lib/src/io_cross_file.dart | 20 +++++++++++++++---- .../test/io_cross_file_test.dart | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 786248f072d5..cc1da0ef3fba 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -47,14 +47,26 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { PlatformXFileExtension? get extension => this; @override - Future lastModified() async => file.lastModifiedSync(); + Future lastModified() async { + try { + return file.lastModifiedSync(); + } on FileSystemException { + return null; + } + } @override - Future length() => file.length(); + Future length() async { + try { + return file.length(); + } on FileSystemException { + return null; + } + } @override - Stream> openRead([int? start, int? end]) => - file.openRead(start, end); + Stream openRead([int? start, int? end]) => + file.openRead(start, end).cast(); @override Future readAsBytes() => file.readAsBytes(); diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index 18548ad1ddf0..33087c169933 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -24,7 +24,7 @@ void main() { PlatformXFileCreationParams(uri: testFile.path), ); - expect(await file.lastModified(), await testFile.lastModified()); + expect(await file.lastModified(), testFile.lastModifiedSync()); }); test('length', () async { From b0dee72d71e41c05231b395cef46b120fcc644c6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 15 Jan 2026 15:49:52 -0500 Subject: [PATCH 084/398] update nullable methods --- .../cross_file/cross_file_web/lib/src/web_cross_file.dart | 6 +++--- packages/cross_file/cross_file_web/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index 7eb3ed52c717..d9d6e3145d42 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -95,17 +95,17 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { } @override - Future lastModified() async { + Future lastModified() async { final Blob blob = await getBlob(); if (blob is File) { return DateTime.fromMillisecondsSinceEpoch(blob.lastModified); } - return DateTime.now(); + return null; } @override - Future length() async { + Future length() async { return (await getBlob()).size; } diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 7468d0ae0992..41c11bce300f 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -17,13 +17,13 @@ flutter: fileName: cross_file_web.dart dependencies: + cross_file_platform_interface: + path: ../cross_file_platform_interface flutter: sdk: flutter flutter_web_plugins: sdk: flutter web: ">=0.5.1 <2.0.0" - cross_file_platform_interface: - path: ../cross_file_platform_interface dev_dependencies: flutter_test: From 3fac71be9e20962d17893be709ff10e6f100685a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:41:26 -0500 Subject: [PATCH 085/398] improve web tests --- .../lib/src/web_cross_file.dart | 2 +- .../test/web_cross_file_test.dart | 228 ++++++++++++------ 2 files changed, 151 insertions(+), 79 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index d9d6e3145d42..f895bc76c770 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -71,7 +71,7 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { late final WebXFileCreationParams params = super.params is WebXFileCreationParams ? super.params as WebXFileCreationParams - : UrlWebXFileCreationParams(objectUrl: params.uri); + : UrlWebXFileCreationParams(objectUrl: super.params.uri); @override Future getBlob() async { diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index 7145e62900e0..7760784cb93b 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -9,122 +9,194 @@ import 'dart:convert'; import 'dart:js_interop'; import 'dart:typed_data'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:cross_file_web/cross_file_web.dart'; import 'package:cross_file_web/src/web_cross_file.dart'; import 'package:cross_file_web/src/web_helpers.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:web/web.dart' as html; -const String expectedStringContents = 'Hello, world! I ❤ ñ! 空手'; -final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); -final html.File textFile = html.File( - [bytes.toJS].toJS, +const String testFileStringContents = 'Hello, world! I ❤ ñ! 空手'; +final Uint8List testFileBytes = Uint8List.fromList( + utf8.encode(testFileStringContents), +); +final html.File testFile = html.File( + [testFileBytes.toJS].toJS, 'hello.txt', ); -final String textFileUrl = html.URL.createObjectURL(textFile as JSObject); +final String testFileUrl = html.URL.createObjectURL(testFile as JSObject); void main() { - group('Create with an objectUrl', () { - final file = WebXFile(UrlWebXFileCreationParams(objectUrl: textFileUrl)); + group('WebXFile', () { + CrossFilePlatform.instance = CrossFileWeb(); - test('Can be read as a string', () async { - expect(await file.readAsString(), equals(expectedStringContents)); - }); + group('Create with url', () { + test('openRead', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFileUrl), + ); - test('Can be read as bytes', () async { - expect(await file.readAsBytes(), equals(bytes)); - }); + expect(await file.openRead().first, testFileBytes); + }); - test('Can be read as a stream', () async { - expect(await file.openRead().first, equals(bytes)); - }); + test('openRead with partial data', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFileUrl), + ); - test('Stream can be sliced', () async { - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - }); + expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); + }); - group('Blob backend', () { - final file = WebXFile(BlobWebXFileCreationParams(textFile)); + test('readAsBytes', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFileUrl), + ); - test('Stores data as a Blob', () async { - // Read the blob from its path 'natively' - final html.Response response = await html.window - .fetch(file.params.uri.toJS) - .toDart; + expect(await file.readAsBytes(), testFileBytes); + }); - final JSAny arrayBuffer = await response.arrayBuffer().toDart; - final ByteBuffer data = (arrayBuffer as JSArrayBuffer).toDart; - expect(data.asUint8List(), equals(bytes)); - }); + test('readAsString', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFileUrl), + ); - test('Data may be purged from the blob!', () async { - html.URL.revokeObjectURL(file.params.uri); + expect(await file.readAsString(), testFileStringContents); + }); - final urlFile = WebXFile( - UrlWebXFileCreationParams(objectUrl: file.params.uri), - ); + test('canRead', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFileUrl), + ); - await expectLater(() => urlFile.readAsString(), throwsException); - }); - }); + expect(await file.canRead(), true); + }); - group('download', () { - const crossFileDomElementId = '__x_file_dom_element'; + test('exists', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFileUrl), + ); - group('XFile download', () { - test('creates a DOM container', () async { - final file = WebXFile(BlobWebXFileCreationParams(textFile)); + expect(await file.exists(), true); + }); + }); - await file.download(''); + group('Create with File', () { + test('lastModified', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); - final html.Element? container = html.document.querySelector( - '#$crossFileDomElementId', + expect( + await file.lastModified(), + DateTime.fromMillisecondsSinceEpoch(testFile.lastModified), ); + }); + + test('length', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); - expect(container, isNotNull); + expect(await file.length(), testFile.size); }); - test('create anchor element', () async { - final file = WebXFile(BlobWebXFileCreationParams(textFile)); + test('openRead', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); - await file.download('path'); + expect(await file.openRead().first, testFileBytes); + }); - final html.Element container = html.document.querySelector( - '#$crossFileDomElementId', - )!; + test('openRead with partial data', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); - late html.HTMLAnchorElement element; - for (var i = 0; i < container.childNodes.length; i++) { - final html.Element test = container.children.item(i)!; - if (test.tagName == 'A') { - element = test as html.HTMLAnchorElement; - break; - } - } + expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); + }); - // if element is not found, the `firstWhere` call will throw StateError. - expect(element.href, file.params.uri); - expect(element.download, 'path'); + test('readAsBytes', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + + expect(await file.readAsBytes(), testFileBytes); }); - test('anchor element is clicked', () async { - final mockAnchor = - html.document.createElement('a') as html.HTMLAnchorElement; + test('readAsString', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); - final testOverrides = XFileTestOverrides( - createAnchorElement: (_, __) => mockAnchor, - ); + expect(await file.readAsString(), testFileStringContents); + }); - final file = WebXFile( - BlobWebXFileCreationParams(textFile, testOverrides: testOverrides), - ); + test('canRead', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + + expect(await file.canRead(), true); + }); + + test('exists', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + + expect(await file.exists(), true); + }); + + test('name', () async { + final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + + expect(await file.name(), testFile.name); + }); + }); + + group('download', () { + const crossFileDomElementId = '__x_file_dom_element'; + + group('XFile download', () { + test('creates a DOM container', () async { + final file = WebXFile(BlobWebXFileCreationParams(testFile)); + + await file.download(''); + + final html.Element? container = html.document.querySelector( + '#$crossFileDomElementId', + ); + + expect(container, isNotNull); + }); + + test('create anchor element', () async { + final file = WebXFile(BlobWebXFileCreationParams(testFile)); + + await file.download('path'); + + final html.Element container = html.document.querySelector( + '#$crossFileDomElementId', + )!; + + late html.HTMLAnchorElement element; + for (var i = 0; i < container.childNodes.length; i++) { + final html.Element test = container.children.item(i)!; + if (test.tagName == 'A') { + element = test as html.HTMLAnchorElement; + break; + } + } + + // if element is not found, the `firstWhere` call will throw StateError. + expect(element.href, file.params.uri); + expect(element.download, 'path'); + }); + + test('anchor element is clicked', () async { + final mockAnchor = + html.document.createElement('a') as html.HTMLAnchorElement; + + final testOverrides = XFileTestOverrides( + createAnchorElement: (_, __) => mockAnchor, + ); + + final file = WebXFile( + BlobWebXFileCreationParams(testFile, testOverrides: testOverrides), + ); - var clicked = false; - mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); + var clicked = false; + mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); - await file.download('path'); + await file.download('path'); - expect(clicked, true); + expect(clicked, true); + }); }); }); }); From e5d762cfc2ad08bda25341a27fea4f0b790f1d68 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 15 Jan 2026 16:53:31 -0500 Subject: [PATCH 086/398] update descriptions --- packages/cross_file/cross_file_android/pubspec.yaml | 2 +- packages/cross_file/cross_file_io/pubspec.yaml | 2 +- packages/cross_file/cross_file_web/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 720838a3758d..01df121bbcc9 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -1,5 +1,5 @@ name: cross_file_android -description: Some something darkside +description: Implementation of cross_file_platform_interface for Android. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index c59681ad1d38..f4718c7f75f7 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -1,5 +1,5 @@ name: cross_file_io -description: Something something darkside +description: Implementation of cross_file_platform_interface for dart:io. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_io issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 41c11bce300f..3c68441fcebb 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -1,5 +1,5 @@ name: cross_file_web -description: A Flutter plugin that provides a WebView widget on web. +description: Implementation of cross_file_platform_interface for web. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 From 612271d6195a4ba53c95b2b159871fdd3d9e4991 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 15 Jan 2026 17:00:40 -0500 Subject: [PATCH 087/398] update android shared to scoped --- ...droid_scoped_storage_cross_directory.dart} | 18 ++++---- ...=> android_scoped_storage_cross_file.dart} | 8 ++-- .../lib/src/cross_file_android.dart | 16 +++---- ...d_shared_storage_cross_directory_test.dart | 10 ++--- ...ndroid_shared_storage_cross_file_test.dart | 44 +++++++++---------- 5 files changed, 48 insertions(+), 48 deletions(-) rename packages/cross_file/cross_file_android/lib/src/{android_shared_storage_cross_directory.dart => android_scoped_storage_cross_directory.dart} (66%) rename packages/cross_file/cross_file_android/lib/src/{android_shared_storage_cross_file.dart => android_scoped_storage_cross_file.dart} (92%) diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart similarity index 66% rename from packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart rename to packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index 7fa483efc9ed..dfd5973f2eef 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -5,13 +5,13 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'android_library.g.dart'; -import 'android_shared_storage_cross_file.dart'; +import 'android_scoped_storage_cross_file.dart'; /// Implementation of [PlatformSharedStorageXDirectory] for Android. -base class AndroidSharedStorageXDirectory - extends PlatformSharedStorageXDirectory { - /// Constructs an [AndroidSharedStorageXDirectory]. - AndroidSharedStorageXDirectory(super.params) : super.implementation(); +base class AndroidScopedStorageXDirectory + extends PlatformScopedStorageXDirectory { + /// Constructs an [AndroidScopedStorageXDirectory]. + AndroidScopedStorageXDirectory(super.params) : super.implementation(); late final DocumentFile _documentFile = DocumentFile.fromTreeUri( treeUri: params.uri, @@ -27,12 +27,12 @@ base class AndroidSharedStorageXDirectory for (final DocumentFile documentFile in await _documentFile.listFiles()) { final String uri = await documentFile.getUri(); if (await documentFile.isFile()) { - yield AndroidSharedStorageXFile( - PlatformSharedStorageXFileCreationParams(uri: uri), + yield AndroidScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: uri), ); } else if (await documentFile.isDirectory()) { - yield AndroidSharedStorageXDirectory( - PlatformSharedStorageXDirectoryCreationParams(uri: uri), + yield AndroidScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams(uri: uri), ); } } diff --git a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart similarity index 92% rename from packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart rename to packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index c596c9b4b867..504a59a148d4 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -10,10 +10,10 @@ import 'package:flutter/foundation.dart'; import 'android_library.g.dart' as android; -/// Implementation of [PlatformSharedStorageXFile] for Android. -base class AndroidSharedStorageXFile extends PlatformSharedStorageXFile { - /// Constructs an [AndroidSharedStorageXFile]. - AndroidSharedStorageXFile(super.params) : super.implementation(); +/// Implementation of [PlatformScopedStorageXFile] for Android. +base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { + /// Constructs an [AndroidScopedStorageXFile]. + AndroidScopedStorageXFile(super.params) : super.implementation(); late final android.DocumentFile _documentFile = android.DocumentFile.fromSingleUri(singleUri: params.uri); diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index 82389e9fae47..b3b6c47a5017 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -5,8 +5,8 @@ import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'android_shared_storage_cross_directory.dart'; -import 'android_shared_storage_cross_file.dart'; +import 'android_scoped_storage_cross_directory.dart'; +import 'android_scoped_storage_cross_file.dart'; /// Implementation of [CrossFilePlatform] for Android. base class CrossFileAndroid extends CrossFileIO { @@ -16,16 +16,16 @@ base class CrossFileAndroid extends CrossFileIO { } @override - AndroidSharedStorageXFile createPlatformSharedStorageXFile( - PlatformSharedStorageXFileCreationParams params, + AndroidScopedStorageXFile createPlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, ) { - return AndroidSharedStorageXFile(params); + return AndroidScopedStorageXFile(params); } @override - PlatformSharedStorageXDirectory createPlatformSharedStorageXDirectory( - PlatformSharedStorageXDirectoryCreationParams params, + AndroidScopedStorageXDirectory createPlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams params, ) { - return AndroidSharedStorageXDirectory(params); + return AndroidScopedStorageXDirectory(params); } } diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart index b802ea136493..07466d227ef1 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:cross_file_android/src/android_library.g.dart' as android; -import 'package:cross_file_android/src/android_shared_storage_cross_directory.dart'; +import 'package:cross_file_android/src/android_scoped_storage_cross_directory.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; @@ -31,8 +31,8 @@ void main() { return mockDocumentFile; }; - final file = AndroidSharedStorageXDirectory( - const PlatformSharedStorageXDirectoryCreationParams(uri: uri), + final file = AndroidScopedStorageXDirectory( + const PlatformScopedStorageXDirectoryCreationParams(uri: uri), ); expect(await file.exists(), true); @@ -61,8 +61,8 @@ void main() { return mockFile; }; - final dir = AndroidSharedStorageXDirectory( - const PlatformSharedStorageXDirectoryCreationParams(uri: uri), + final dir = AndroidScopedStorageXDirectory( + const PlatformScopedStorageXDirectoryCreationParams(uri: uri), ); final List entityUris = await dir diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart index daad742929d8..6b2219252933 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart @@ -6,7 +6,7 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:cross_file_android/src/android_library.g.dart' as android; -import 'package:cross_file_android/src/android_shared_storage_cross_file.dart'; +import 'package:cross_file_android/src/android_scoped_storage_cross_file.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; @@ -38,8 +38,8 @@ void main() { return mockDocumentFile; }; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect( @@ -60,8 +60,8 @@ void main() { return mockDocumentFile; }; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(await file.length(), length); @@ -130,8 +130,8 @@ void main() { ).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(combineLists(await file.openRead().toList()), testBytes); @@ -141,7 +141,7 @@ void main() { 'openRead finishes successfully with file larger than max array len', () async { final testBytes = Uint8List.fromList( - List.filled(AndroidSharedStorageXFile.maxByteArrayLen + 1, 0), + List.filled(AndroidScopedStorageXFile.maxByteArrayLen + 1, 0), ); final mockDocumentFile = MockDocumentFile(); @@ -165,8 +165,8 @@ void main() { ).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(combineLists(await file.openRead().toList()), testBytes); @@ -195,8 +195,8 @@ void main() { ).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(combineLists(await file.openRead(3, 6).toList()), [1, 1, 1]); @@ -225,8 +225,8 @@ void main() { ).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(await file.readAsBytes(), testBytes); @@ -255,8 +255,8 @@ void main() { ).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(await file.readAsString(), testString); @@ -274,8 +274,8 @@ void main() { return mockDocumentFile; }; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(await file.canRead(), canRead); @@ -293,8 +293,8 @@ void main() { return mockDocumentFile; }; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(await file.exists(), true); @@ -312,8 +312,8 @@ void main() { return mockDocumentFile; }; - final file = AndroidSharedStorageXFile( - const PlatformSharedStorageXFileCreationParams(uri: uri), + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), ); expect(await file.name(), name); From 14da44b8db198e1ff3ef5b6be1545ff00adfffe9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:08:14 -0500 Subject: [PATCH 088/398] update android scoped storage --- .../android_scoped_storage_cross_file.dart | 27 +- ..._scoped_storage_cross_directory_test.dart} | 2 +- ...droid_scoped_storage_cross_file_test.dart} | 84 +++--- ...ed_storage_cross_directory_test.mocks.dart | 151 ---------- ..._shared_storage_cross_file_test.mocks.dart | 270 ------------------ 5 files changed, 64 insertions(+), 470 deletions(-) rename packages/cross_file/cross_file_android/test/{android_shared_storage_cross_directory_test.dart => android_scoped_storage_cross_directory_test.dart} (97%) rename packages/cross_file/cross_file_android/test/{android_shared_storage_cross_file_test.dart => android_scoped_storage_cross_file_test.dart} (86%) delete mode 100644 packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart delete mode 100644 packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 504a59a148d4..655eb0f439a9 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -29,18 +29,33 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { static const int maxByteArrayLen = 4 * 1024; @override - Future lastModified() async { - return DateTime.fromMillisecondsSinceEpoch( - await _documentFile.lastModified(), - ); + Future lastModified() async { + final int msSinceEpoch = await _documentFile.lastModified(); + if (msSinceEpoch == 0) { + return null; + } + + return DateTime.fromMillisecondsSinceEpoch(msSinceEpoch); } @override - Future length() => _documentFile.length(); + Future length() async { + final int length = await _documentFile.length(); + if (length == 0) { + return null; + } + + return length; + } @override Stream openRead([int? start, int? end]) async* { - int bytesToRead = (end ?? await length()) - (start ?? 0); + final int? fileLength = await length(); + if (fileLength == null) { + throw UnsupportedError('Can not access file length.'); + } + + int bytesToRead = (end ?? fileLength) - (start ?? 0); assert(bytesToRead >= 0); final android.InputStream? inputStream = await _contentResolver diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart similarity index 97% rename from packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart rename to packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart index 07466d227ef1..cfb389489db2 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart @@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'android_shared_storage_cross_directory_test.mocks.dart'; +import 'android_scoped_storage_cross_directory_test.mocks.dart'; @GenerateMocks([android.DocumentFile]) void main() { diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart similarity index 86% rename from packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart rename to packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart index 6b2219252933..a7c85762c3be 100644 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart @@ -12,7 +12,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'android_shared_storage_cross_file_test.mocks.dart'; +import 'android_scoped_storage_cross_file_test.mocks.dart'; @GenerateMocks([ android.ContentResolver, @@ -68,46 +68,6 @@ void main() { }); group('openRead', () { - void setUpInputStreamWithBytes( - MockInputStream mockInputStream, - Uint8List bytes, - ) { - Iterable remainingBytes = bytes.toList(); - - when(mockInputStream.skip(any)).thenAnswer((Invocation invocation) async { - final amount = invocation.positionalArguments[0] as int; - if (amount < 0) { - return 0; - } - - final Iterable newRemainingBytes = remainingBytes.skip(amount); - - final int diff = remainingBytes.length - newRemainingBytes.length; - remainingBytes = newRemainingBytes; - return diff; - }); - - when(mockInputStream.readBytes(any)).thenAnswer(( - Invocation invocation, - ) async { - final len = invocation.positionalArguments[0] as int; - - final List bytesRead = remainingBytes.take(len).toList(); - remainingBytes = remainingBytes.skip(len); - - return android.InputStreamReadBytesResponse.pigeon_detached( - returnValue: remainingBytes.isEmpty ? -1 : bytesRead.length, - bytes: Uint8List.fromList(bytesRead), - ); - }); - } - - Uint8List combineLists(List lists) { - return Uint8List.fromList( - lists.expand((Uint8List element) => element).toList(), - ); - } - test('openRead finishes successfully', () async { final testBytes = Uint8List.fromList([0, 1, 2]); @@ -247,7 +207,7 @@ void main() { }; final mockInputStream = MockInputStream(); - when(mockInputStream.readAllBytes()).thenAnswer((_) async => testBytes); + setUpInputStreamWithBytes(mockInputStream, testBytes); final mockContentResolver = MockContentResolver(); when( @@ -319,3 +279,43 @@ void main() { expect(await file.name(), name); }); } + +void setUpInputStreamWithBytes( + MockInputStream mockInputStream, + Uint8List bytes, +) { + Iterable remainingBytes = bytes.toList(); + + when(mockInputStream.skip(any)).thenAnswer((Invocation invocation) async { + final amount = invocation.positionalArguments[0] as int; + if (amount < 0) { + return 0; + } + + final Iterable newRemainingBytes = remainingBytes.skip(amount); + + final int diff = remainingBytes.length - newRemainingBytes.length; + remainingBytes = newRemainingBytes; + return diff; + }); + + when(mockInputStream.readBytes(any)).thenAnswer(( + Invocation invocation, + ) async { + final len = invocation.positionalArguments[0] as int; + + final List bytesRead = remainingBytes.take(len).toList(); + remainingBytes = remainingBytes.skip(len); + + return android.InputStreamReadBytesResponse.pigeon_detached( + returnValue: remainingBytes.isEmpty ? -1 : bytesRead.length, + bytes: Uint8List.fromList(bytesRead), + ); + }); +} + +Uint8List combineLists(List lists) { + return Uint8List.fromList( + lists.expand((Uint8List element) => element).toList(), + ); +} diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart deleted file mode 100644 index cb5504888623..000000000000 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_directory_test.mocks.dart +++ /dev/null @@ -1,151 +0,0 @@ -// Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_android/test/android_shared_storage_cross_directory_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i3; - -import 'package:cross_file_android/src/android_library.g.dart' as _i2; -import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i4; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class -// ignore_for_file: invalid_use_of_internal_member - -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { - _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeDocumentFile_1 extends _i1.SmartFake implements _i2.DocumentFile { - _FakeDocumentFile_1(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -/// A class which mocks [DocumentFile]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { - MockDocumentFile() { - _i1.throwOnMissingStub(this); - } - - @override - _i2.PigeonInstanceManager get pigeon_instanceManager => - (super.noSuchMethod( - Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_0( - this, - Invocation.getter(#pigeon_instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override - _i3.Future canRead() => - (super.noSuchMethod( - Invocation.method(#canRead, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future delete() => - (super.noSuchMethod( - Invocation.method(#delete, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future exists() => - (super.noSuchMethod( - Invocation.method(#exists, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future lastModified() => - (super.noSuchMethod( - Invocation.method(#lastModified, []), - returnValue: _i3.Future.value(0), - ) - as _i3.Future); - - @override - _i3.Future length() => - (super.noSuchMethod( - Invocation.method(#length, []), - returnValue: _i3.Future.value(0), - ) - as _i3.Future); - - @override - _i3.Future isFile() => - (super.noSuchMethod( - Invocation.method(#isFile, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future isDirectory() => - (super.noSuchMethod( - Invocation.method(#isDirectory, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future> listFiles() => - (super.noSuchMethod( - Invocation.method(#listFiles, []), - returnValue: _i3.Future>.value( - <_i2.DocumentFile>[], - ), - ) - as _i3.Future>); - - @override - _i3.Future getUri() => - (super.noSuchMethod( - Invocation.method(#getUri, []), - returnValue: _i3.Future.value( - _i4.dummyValue(this, Invocation.method(#getUri, [])), - ), - ) - as _i3.Future); - - @override - _i3.Future getName() => - (super.noSuchMethod( - Invocation.method(#getName, []), - returnValue: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i2.DocumentFile pigeon_copy() => - (super.noSuchMethod( - Invocation.method(#pigeon_copy, []), - returnValue: _FakeDocumentFile_1( - this, - Invocation.method(#pigeon_copy, []), - ), - ) - as _i2.DocumentFile); -} diff --git a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart deleted file mode 100644 index 6d769a543149..000000000000 --- a/packages/cross_file/cross_file_android/test/android_shared_storage_cross_file_test.mocks.dart +++ /dev/null @@ -1,270 +0,0 @@ -// Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_android/test/android_shared_storage_cross_file_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i3; -import 'dart:typed_data' as _i5; - -import 'package:cross_file_android/src/android_library.g.dart' as _i2; -import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i4; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class -// ignore_for_file: invalid_use_of_internal_member - -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { - _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeContentResolver_1 extends _i1.SmartFake - implements _i2.ContentResolver { - _FakeContentResolver_1(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeDocumentFile_2 extends _i1.SmartFake implements _i2.DocumentFile { - _FakeDocumentFile_2(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeInputStreamReadBytesResponse_3 extends _i1.SmartFake - implements _i2.InputStreamReadBytesResponse { - _FakeInputStreamReadBytesResponse_3( - Object parent, - Invocation parentInvocation, - ) : super(parent, parentInvocation); -} - -class _FakeInputStream_4 extends _i1.SmartFake implements _i2.InputStream { - _FakeInputStream_4(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -/// A class which mocks [ContentResolver]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { - MockContentResolver() { - _i1.throwOnMissingStub(this); - } - - @override - _i2.PigeonInstanceManager get pigeon_instanceManager => - (super.noSuchMethod( - Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_0( - this, - Invocation.getter(#pigeon_instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override - _i3.Future<_i2.InputStream?> openInputStream(String? uri) => - (super.noSuchMethod( - Invocation.method(#openInputStream, [uri]), - returnValue: _i3.Future<_i2.InputStream?>.value(), - ) - as _i3.Future<_i2.InputStream?>); - - @override - _i2.ContentResolver pigeon_copy() => - (super.noSuchMethod( - Invocation.method(#pigeon_copy, []), - returnValue: _FakeContentResolver_1( - this, - Invocation.method(#pigeon_copy, []), - ), - ) - as _i2.ContentResolver); -} - -/// A class which mocks [DocumentFile]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { - MockDocumentFile() { - _i1.throwOnMissingStub(this); - } - - @override - _i2.PigeonInstanceManager get pigeon_instanceManager => - (super.noSuchMethod( - Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_0( - this, - Invocation.getter(#pigeon_instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override - _i3.Future canRead() => - (super.noSuchMethod( - Invocation.method(#canRead, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future delete() => - (super.noSuchMethod( - Invocation.method(#delete, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future exists() => - (super.noSuchMethod( - Invocation.method(#exists, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future lastModified() => - (super.noSuchMethod( - Invocation.method(#lastModified, []), - returnValue: _i3.Future.value(0), - ) - as _i3.Future); - - @override - _i3.Future length() => - (super.noSuchMethod( - Invocation.method(#length, []), - returnValue: _i3.Future.value(0), - ) - as _i3.Future); - - @override - _i3.Future isFile() => - (super.noSuchMethod( - Invocation.method(#isFile, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future isDirectory() => - (super.noSuchMethod( - Invocation.method(#isDirectory, []), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future> listFiles() => - (super.noSuchMethod( - Invocation.method(#listFiles, []), - returnValue: _i3.Future>.value( - <_i2.DocumentFile>[], - ), - ) - as _i3.Future>); - - @override - _i3.Future getUri() => - (super.noSuchMethod( - Invocation.method(#getUri, []), - returnValue: _i3.Future.value( - _i4.dummyValue(this, Invocation.method(#getUri, [])), - ), - ) - as _i3.Future); - - @override - _i3.Future getName() => - (super.noSuchMethod( - Invocation.method(#getName, []), - returnValue: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i2.DocumentFile pigeon_copy() => - (super.noSuchMethod( - Invocation.method(#pigeon_copy, []), - returnValue: _FakeDocumentFile_2( - this, - Invocation.method(#pigeon_copy, []), - ), - ) - as _i2.DocumentFile); -} - -/// A class which mocks [InputStream]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockInputStream extends _i1.Mock implements _i2.InputStream { - MockInputStream() { - _i1.throwOnMissingStub(this); - } - - @override - _i2.PigeonInstanceManager get pigeon_instanceManager => - (super.noSuchMethod( - Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_0( - this, - Invocation.getter(#pigeon_instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override - _i3.Future<_i2.InputStreamReadBytesResponse> readBytes(int? len) => - (super.noSuchMethod( - Invocation.method(#readBytes, [len]), - returnValue: _i3.Future<_i2.InputStreamReadBytesResponse>.value( - _FakeInputStreamReadBytesResponse_3( - this, - Invocation.method(#readBytes, [len]), - ), - ), - ) - as _i3.Future<_i2.InputStreamReadBytesResponse>); - - @override - _i3.Future<_i5.Uint8List> readAllBytes() => - (super.noSuchMethod( - Invocation.method(#readAllBytes, []), - returnValue: _i3.Future<_i5.Uint8List>.value(_i5.Uint8List(0)), - ) - as _i3.Future<_i5.Uint8List>); - - @override - _i3.Future skip(int? n) => - (super.noSuchMethod( - Invocation.method(#skip, [n]), - returnValue: _i3.Future.value(0), - ) - as _i3.Future); - - @override - _i2.InputStream pigeon_copy() => - (super.noSuchMethod( - Invocation.method(#pigeon_copy, []), - returnValue: _FakeInputStream_4( - this, - Invocation.method(#pigeon_copy, []), - ), - ) - as _i2.InputStream); -} From e44b6f49db1a7b8cca65bd0bbe0f575d05ecd7e3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:08:28 -0500 Subject: [PATCH 089/398] add mocks --- ...ed_storage_cross_directory_test.mocks.dart | 151 ++++++++++ ..._scoped_storage_cross_file_test.mocks.dart | 270 ++++++++++++++++++ 2 files changed, 421 insertions(+) create mode 100644 packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart create mode 100644 packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart new file mode 100644 index 000000000000..f4bac06e92f6 --- /dev/null +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart @@ -0,0 +1,151 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_android/test/android_scoped_storage_cross_directory_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:cross_file_android/src/android_library.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDocumentFile_1 extends _i1.SmartFake implements _i2.DocumentFile { + _FakeDocumentFile_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [DocumentFile]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { + MockDocumentFile() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future canRead() => + (super.noSuchMethod( + Invocation.method(#canRead, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future delete() => + (super.noSuchMethod( + Invocation.method(#delete, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future exists() => + (super.noSuchMethod( + Invocation.method(#exists, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future lastModified() => + (super.noSuchMethod( + Invocation.method(#lastModified, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future length() => + (super.noSuchMethod( + Invocation.method(#length, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future isFile() => + (super.noSuchMethod( + Invocation.method(#isFile, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future isDirectory() => + (super.noSuchMethod( + Invocation.method(#isDirectory, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future> listFiles() => + (super.noSuchMethod( + Invocation.method(#listFiles, []), + returnValue: _i3.Future>.value( + <_i2.DocumentFile>[], + ), + ) + as _i3.Future>); + + @override + _i3.Future getUri() => + (super.noSuchMethod( + Invocation.method(#getUri, []), + returnValue: _i3.Future.value( + _i4.dummyValue(this, Invocation.method(#getUri, [])), + ), + ) + as _i3.Future); + + @override + _i3.Future getName() => + (super.noSuchMethod( + Invocation.method(#getName, []), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i2.DocumentFile pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeDocumentFile_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.DocumentFile); +} diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart new file mode 100644 index 000000000000..6392c7ba2670 --- /dev/null +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart @@ -0,0 +1,270 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_android/test/android_scoped_storage_cross_file_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; +import 'dart:typed_data' as _i5; + +import 'package:cross_file_android/src/android_library.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i4; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeContentResolver_1 extends _i1.SmartFake + implements _i2.ContentResolver { + _FakeContentResolver_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeDocumentFile_2 extends _i1.SmartFake implements _i2.DocumentFile { + _FakeDocumentFile_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeInputStreamReadBytesResponse_3 extends _i1.SmartFake + implements _i2.InputStreamReadBytesResponse { + _FakeInputStreamReadBytesResponse_3( + Object parent, + Invocation parentInvocation, + ) : super(parent, parentInvocation); +} + +class _FakeInputStream_4 extends _i1.SmartFake implements _i2.InputStream { + _FakeInputStream_4(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [ContentResolver]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { + MockContentResolver() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future<_i2.InputStream?> openInputStream(String? uri) => + (super.noSuchMethod( + Invocation.method(#openInputStream, [uri]), + returnValue: _i3.Future<_i2.InputStream?>.value(), + ) + as _i3.Future<_i2.InputStream?>); + + @override + _i2.ContentResolver pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeContentResolver_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.ContentResolver); +} + +/// A class which mocks [DocumentFile]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { + MockDocumentFile() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future canRead() => + (super.noSuchMethod( + Invocation.method(#canRead, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future delete() => + (super.noSuchMethod( + Invocation.method(#delete, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future exists() => + (super.noSuchMethod( + Invocation.method(#exists, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future lastModified() => + (super.noSuchMethod( + Invocation.method(#lastModified, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future length() => + (super.noSuchMethod( + Invocation.method(#length, []), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i3.Future isFile() => + (super.noSuchMethod( + Invocation.method(#isFile, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future isDirectory() => + (super.noSuchMethod( + Invocation.method(#isDirectory, []), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future> listFiles() => + (super.noSuchMethod( + Invocation.method(#listFiles, []), + returnValue: _i3.Future>.value( + <_i2.DocumentFile>[], + ), + ) + as _i3.Future>); + + @override + _i3.Future getUri() => + (super.noSuchMethod( + Invocation.method(#getUri, []), + returnValue: _i3.Future.value( + _i4.dummyValue(this, Invocation.method(#getUri, [])), + ), + ) + as _i3.Future); + + @override + _i3.Future getName() => + (super.noSuchMethod( + Invocation.method(#getName, []), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i2.DocumentFile pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeDocumentFile_2( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.DocumentFile); +} + +/// A class which mocks [InputStream]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockInputStream extends _i1.Mock implements _i2.InputStream { + MockInputStream() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future<_i2.InputStreamReadBytesResponse> readBytes(int? len) => + (super.noSuchMethod( + Invocation.method(#readBytes, [len]), + returnValue: _i3.Future<_i2.InputStreamReadBytesResponse>.value( + _FakeInputStreamReadBytesResponse_3( + this, + Invocation.method(#readBytes, [len]), + ), + ), + ) + as _i3.Future<_i2.InputStreamReadBytesResponse>); + + @override + _i3.Future<_i5.Uint8List> readAllBytes() => + (super.noSuchMethod( + Invocation.method(#readAllBytes, []), + returnValue: _i3.Future<_i5.Uint8List>.value(_i5.Uint8List(0)), + ) + as _i3.Future<_i5.Uint8List>); + + @override + _i3.Future skip(int? n) => + (super.noSuchMethod( + Invocation.method(#skip, [n]), + returnValue: _i3.Future.value(0), + ) + as _i3.Future); + + @override + _i2.InputStream pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeInputStream_4( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.InputStream); +} From 964a8858d70e16071449b4c4769d7f4237851815 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:24:18 -0500 Subject: [PATCH 090/398] maybe improve android later --- .../cross_file_android/pigeons/android_library.dart | 10 +++++++++- ...file.dart => darwin_scoped_storage_cross_file.dart} | 0 2 files changed, 9 insertions(+), 1 deletion(-) rename packages/cross_file/cross_file_darwin/lib/src/{darwin_shared_storage_cross_file.dart => darwin_scoped_storage_cross_file.dart} (100%) diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index 5b9d4a99a591..7da2829f0349 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -30,6 +30,8 @@ abstract class DocumentFile { /// Create a DocumentFile representing the single document at the given Uri. DocumentFile.fromSingleUri(String singleUri); + /// Create a DocumentFile representing the document tree rooted at the given + /// Uri. DocumentFile.fromTreeUri(String treeUri); /// Indicates whether the current context is allowed to read from this file. @@ -91,8 +93,13 @@ abstract class ContentResolver { ), ) abstract class InputStreamReadBytesResponse { - late final int returnValue; + /// The total number of bytes read into `bytes`, or -1 if there is no more + /// data because the end of the stream has been reached. + /// + /// The returned value when calling the native `InputStream.readBytes` method. + late final int bytesRead; + /// The byte array into which the data is read. late final Uint8List bytes; } @@ -104,6 +111,7 @@ abstract class InputStreamReadBytesResponse { kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), ) abstract class InputStream { + // TODO: maybe return empty list instead of new class? /// Reads some number of bytes from the input stream and stores them into the /// returns them. InputStreamReadBytesResponse readBytes(int len); diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart similarity index 100% rename from packages/cross_file/cross_file_darwin/lib/src/darwin_shared_storage_cross_file.dart rename to packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart From d2aaf84022d1314a6ae55ccca5ada4c649b33a18 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:49:21 -0500 Subject: [PATCH 091/398] basic impl --- .../cross_file_android/example/lib/main.dart | 2 +- ...ndroid_scoped_storage_cross_directory.dart | 2 +- .../android_scoped_storage_cross_file.dart | 4 +- .../lib/cross_file_darwin.dart | 5 ++ .../lib/src/cross_file_darwin.dart | 31 ++++++++++ ...darwin_scoped_storage_cross_directory.dart | 40 +++++++++++++ .../src/darwin_scoped_storage_cross_file.dart | 59 +++++++++++-------- .../cross_file/cross_file_darwin/pubspec.yaml | 4 +- 8 files changed, 118 insertions(+), 29 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index c9723aa17a50..3a945a835a29 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -31,7 +31,7 @@ class FileOpenScreen extends StatelessWidget { } if (file case final XFile file) { - switch (mime.lookupMimeType(file.path)) { + switch (mime.lookupMimeType(file.name)) { case final String mimeType when mimeType.startsWith('text'): await showDialog( context: context, diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index dfd5973f2eef..ef0d2363e578 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -7,7 +7,7 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'android_library.g.dart'; import 'android_scoped_storage_cross_file.dart'; -/// Implementation of [PlatformSharedStorageXDirectory] for Android. +/// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirectory { /// Constructs an [AndroidScopedStorageXDirectory]. diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 655eb0f439a9..98efdb4c48d1 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -52,7 +52,7 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { Stream openRead([int? start, int? end]) async* { final int? fileLength = await length(); if (fileLength == null) { - throw UnsupportedError('Can not access file length.'); + throw UnsupportedError('Cannot access file length.'); } int bytesToRead = (end ?? fileLength) - (start ?? 0); @@ -92,7 +92,7 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { @override Future readAsString({Encoding encoding = utf8}) async { - return utf8.decodeStream(openRead()); + return encoding.decodeStream(openRead()); } @override diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index b8fa2a34b670..70d1d8383760 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -1,3 +1,8 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. + +export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' + show ListParams, PlatformXFileEntity; + +export 'src/cross_file_darwin.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart new file mode 100644 index 000000000000..f00f2dc02852 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -0,0 +1,31 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'darwin_scoped_storage_cross_directory.dart'; +import 'darwin_scoped_storage_cross_file.dart'; + +/// Implementation of [CrossFilePlatform] for iOS and macOS. +base class CrossFileDarwin extends CrossFileIO { + /// Registers this class as the default instance of [CrossFilePlatform]. + static void registerWith() { + CrossFilePlatform.instance = CrossFileDarwin(); + } + + @override + DarwinScopedStorageXFile createPlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, + ) { + return DarwinScopedStorageXFile(params); + } + + @override + DarwinScopedStorageXDirectory createPlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams params, + ) { + return DarwinScopedStorageXDirectory(params); + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart new file mode 100644 index 000000000000..4b49d777f865 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -0,0 +1,40 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +import 'cross_file_darwin_apis.g.dart'; +import 'darwin_scoped_storage_cross_file.dart'; + +/// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. +base class DarwinScopedStorageXDirectory + extends PlatformScopedStorageXDirectory { + /// Constructs an [DarwinScopedStorageXDirectory]. + DarwinScopedStorageXDirectory(super.params) : super.implementation(); + + late final DocumentFile _documentFile = DocumentFile.fromTreeUri( + treeUri: params.uri, + ); + + @override + Future exists() async { + return await _documentFile.exists() && await _documentFile.isDirectory(); + } + + @override + Stream list(ListParams params) async* { + for (final DocumentFile documentFile in await _documentFile.listFiles()) { + final String uri = await documentFile.getUri(); + if (await documentFile.isFile()) { + yield DarwinScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: uri), + ); + } else if (await documentFile.isDirectory()) { + yield DarwinScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams(uri: uri), + ); + } + } + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index c223e260562b..bd56253ec952 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -11,46 +11,50 @@ import 'package:flutter/foundation.dart'; import 'cross_file_darwin_apis.g.dart'; -/// Implementation of [PlatformSharedStorageXFileCreationParams] for iOS and +/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and /// macOS. @immutable -base class DarwinSharedStorageXFileCreationParams - extends PlatformSharedStorageXFileCreationParams { - /// Constructs a [DarwinSharedStorageXFileCreationParams]. - DarwinSharedStorageXFileCreationParams({ +base class DarwinScopedStorageXFileCreationParams + extends PlatformScopedStorageXFileCreationParams { + /// Constructs a [DarwinScopedStorageXFileCreationParams]. + DarwinScopedStorageXFileCreationParams({ required super.uri, @visibleForTesting CrossFileDarwinApi? api, }) : api = api ?? CrossFileDarwinApi(); + /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; } -/// Implementation of [PlatformSharedStorageXFile] for iOS and macOS. -base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { - /// Constructs a [DarwinSharedStorageXFile]. - DarwinSharedStorageXFile(super.params) : super.implementation(); +/// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. +base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { + /// Constructs a [DarwinScopedStorageXFile]. + DarwinScopedStorageXFile(super.params) : super.implementation(); - /// Maximum number of bytes to read at a time from the native Android - /// InputStream. + /// Maximum number of bytes to read at a time from the native iOS + /// `FileHandle`. /// /// Only visible for testing. @visibleForTesting static const int maxByteArrayLen = 4 * 1024; @override - late final DarwinSharedStorageXFileCreationParams params = - super.params is DarwinSharedStorageXFileCreationParams - ? super.params as DarwinSharedStorageXFileCreationParams - : DarwinSharedStorageXFileCreationParams(uri: params.uri); + late final DarwinScopedStorageXFileCreationParams params = + super.params is DarwinScopedStorageXFileCreationParams + ? super.params as DarwinScopedStorageXFileCreationParams + : DarwinScopedStorageXFileCreationParams(uri: super.params.uri); - Future toBookmarkedFile() async { + /// Retrun + Future toBookmarkedFile() async { final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( params.uri, ); return bookmarkedUrl != null - ? DarwinSharedStorageXFileCreationParams(uri: bookmarkedUrl) + ? DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: bookmarkedUrl), + ) : null; // final URL? url = await _originalUrl; // if (url case URL url) { @@ -80,17 +84,17 @@ base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { Future exists() => params.api.fileExists(params.uri); @override - Future lastModified() async { + Future lastModified() async { final int? lastModifiedSinceEpoch = await params.api.fileModificationDate( params.uri, ); return lastModifiedSinceEpoch != null ? DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch) - : throw UnsupportedError(''); + : null; } @override - Future length() async => await params.api.fileSize(params.uri) ?? 0; + Future length() => params.api.fileSize(params.uri); @override Future name() { @@ -99,7 +103,12 @@ base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { @override Stream openRead([int? start, int? end]) async* { - int bytesToRead = (end ?? await length()) - (start ?? 0); + final int? fileLength = await length(); + if (fileLength == null) { + throw UnsupportedError('Cannot access file length.'); + } + + int bytesToRead = (end ?? fileLength) - (start ?? 0); assert(bytesToRead >= 0); final handle = FileHandle.forReadingFromUrl(url: params.uri); @@ -114,7 +123,9 @@ base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { ); if (bytes == null) { - throw StateError('Failed to read bytes from file: ${params.uri}'); + throw UnsupportedError( + 'Failed to read bytes from file: ${params.uri}', + ); } else { yield bytes; } @@ -132,7 +143,7 @@ base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { try { final Uint8List? bytes = await handle.readToEnd(); if (bytes == null) { - throw StateError('Failed to read bytes from file: ${params.uri}'); + throw UnsupportedError('Failed to read bytes from file: ${params.uri}'); } return bytes; @@ -143,7 +154,7 @@ base class DarwinSharedStorageXFile extends PlatformSharedStorageXFile { @override Future readAsString({Encoding encoding = utf8}) async { - return utf8.decodeStream(openRead()); + return encoding.decodeStream(openRead()); } // late final Future _originalUrl = URL.fileURLWithPath(params.path); diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index d17bc1e2e524..7c056da42136 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -1,5 +1,5 @@ name: cross_file_darwin -description: "A new Flutter plugin project." +description: Implementation of cross_file_platform_interface for iOS and macOS. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_darwin issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 @@ -13,9 +13,11 @@ flutter: implements: cross_file platforms: ios: + dartPluginClass: CrossFileDarwin pluginClass: CrossFileDarwinPlugin sharedDarwinSource: true macos: + dartPluginClass: CrossFileDarwin pluginClass: CrossFileDarwinPlugin sharedDarwinSource: true From 3708c449a3c2001f4675784dac580773f1d579ed Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 18:13:11 -0500 Subject: [PATCH 092/398] finish dart side of impl --- .../Classes/CrossFileDarwinApis.g.swift | 32 +++++++++++ .../lib/src/cross_file_darwin_apis.g.dart | 54 ++++++++++++++++++ ...darwin_scoped_storage_cross_directory.dart | 56 +++++++++++++------ .../src/darwin_scoped_storage_cross_file.dart | 3 +- .../pigeons/cross_file_darwin_apis.dart | 4 ++ 5 files changed, 130 insertions(+), 19 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift index af067d08201e..121593193a97 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -518,8 +518,10 @@ protocol CrossFileDarwinApi { func tryCreateBookmarkedUrl(url: String) throws -> String? func isReadableFile(url: String) throws -> Bool func fileExists(url: String) throws -> Bool + func fileIsDirectory(url: String) throws -> Bool func fileModificationDate(url: String) throws -> Int64? func fileSize(url: String) throws -> Int64? + func list(url: String) throws -> [String] } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -573,6 +575,21 @@ class CrossFileDarwinApiSetup { } else { fileExistsChannel.setMessageHandler(nil) } + let fileIsDirectoryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileIsDirectoryChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileIsDirectory(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileIsDirectoryChannel.setMessageHandler(nil) + } let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileModificationDateChannel.setMessageHandler { message, reply in @@ -603,6 +620,21 @@ class CrossFileDarwinApiSetup { } else { fileSizeChannel.setMessageHandler(nil) } + let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + listChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.list(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + listChannel.setMessageHandler(nil) + } } } protocol PigeonApiDelegateFileHandle { diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index c9772a5bedd8..2acef346003f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -520,6 +520,33 @@ class CrossFileDarwinApi { } } + Future fileIsDirectory(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + Future fileModificationDate(String url) async { final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( @@ -563,6 +590,33 @@ class CrossFileDarwinApi { return (pigeonVar_replyList[0] as int?); } } + + Future> list(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as List?)!.cast(); + } + } } class FileHandle extends PigeonInternalProxyApiBaseClass { factory FileHandle.forReadingFromUrl({ diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 4b49d777f865..484a519ee39a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -3,38 +3,58 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; import 'cross_file_darwin_apis.g.dart'; import 'darwin_scoped_storage_cross_file.dart'; +/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and +/// macOS. +@immutable +base class DarwinScopedStorageXDirectoryCreationParams + extends PlatformScopedStorageXDirectoryCreationParams { + /// Constructs a [PlatformScopedStorageXDirectoryCreationParams]. + DarwinScopedStorageXDirectoryCreationParams({ + required super.uri, + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(); + + /// The API used to call to native code to interact with files. + @visibleForTesting + final CrossFileDarwinApi api; +} + /// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory { /// Constructs an [DarwinScopedStorageXDirectory]. DarwinScopedStorageXDirectory(super.params) : super.implementation(); - late final DocumentFile _documentFile = DocumentFile.fromTreeUri( - treeUri: params.uri, - ); - @override - Future exists() async { - return await _documentFile.exists() && await _documentFile.isDirectory(); + late final DarwinScopedStorageXDirectoryCreationParams params = + super.params is DarwinScopedStorageXDirectoryCreationParams + ? super.params as DarwinScopedStorageXDirectoryCreationParams + : DarwinScopedStorageXDirectoryCreationParams(uri: super.params.uri); + + /// Attempt to create a bookmarked directory that serves as a persistent + /// reference to the directory. + Future toBookmarkedDirectory() async { + final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( + params.uri, + ); + + return bookmarkedUrl != null + ? DarwinScopedStorageXDirectory( + DarwinScopedStorageXDirectoryCreationParams(uri: bookmarkedUrl), + ) + : null; } + @override + Future exists() => params.api.fileExists(params.uri); + @override Stream list(ListParams params) async* { - for (final DocumentFile documentFile in await _documentFile.listFiles()) { - final String uri = await documentFile.getUri(); - if (await documentFile.isFile()) { - yield DarwinScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: uri), - ); - } else if (await documentFile.isDirectory()) { - yield DarwinScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams(uri: uri), - ); - } - } + // list files } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index bd56253ec952..0566d4ed8548 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -45,7 +45,8 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { ? super.params as DarwinScopedStorageXFileCreationParams : DarwinScopedStorageXFileCreationParams(uri: super.params.uri); - /// Retrun + /// Attempt to create a bookmarked file that serves as a persistent reference + /// to the file. Future toBookmarkedFile() async { final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( params.uri, diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index ef3b3b3200de..f709bb882dfc 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -21,9 +21,13 @@ abstract class CrossFileDarwinApi { bool fileExists(String url); + bool fileIsDirectory(String url); + int? fileModificationDate(String url); int? fileSize(String url); + + List list(String url); } @ProxyApi() From bb6f65cfc054391f888a767afb970db7e6aff9ac Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:13:32 -0500 Subject: [PATCH 093/398] format and add generated impl --- .../Classes/CrossFileDarwinApis.g.swift | 207 ++++++++++---- .../Classes/CrossFileDarwinPlugin.swift | 12 +- .../FileHandleProxyAPIDelegate.swift | 38 +++ .../ios/RunnerTests/FileHandleTests.swift | 87 ++++++ .../example/ios/RunnerTests/RunnerTests.swift | 1 - .../macos/RunnerTests/RunnerTests.swift | 6 +- .../lib/src/cross_file_darwin_apis.g.dart | 267 +++++++++++------- 7 files changed, 446 insertions(+), 172 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift create mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift index 121593193a97..90ea47205237 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -59,7 +59,9 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -77,7 +79,6 @@ protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { func onDeinit(identifier: Int64) } - // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -93,14 +94,18 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, + delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( + identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = + objc_getAssociatedObject(instance, associatedObjectKey) + as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -112,7 +117,6 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } - /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -216,7 +220,8 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -297,7 +302,6 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } - private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -310,9 +314,15 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, + instanceManager: CrossFileDarwinApisPigeonInstanceManager? + ) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -327,7 +337,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -343,9 +355,13 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -365,7 +381,8 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiFileHandle } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -378,12 +395,15 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + private class InstanceManagerApiFinalizerDelegate: + CrossFileDarwinApisPigeonInternalFinalizerDelegate + { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -397,7 +417,9 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + init( + binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + ) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -406,18 +428,25 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiFileHandle.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: + FlutterStandardReaderWriter +{ unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: + CrossFileDarwinApisPigeonCodecReader + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -441,7 +470,9 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: + CrossFileDarwinApisPigeonCodecWriter + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -450,24 +481,26 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + { super.writeValue(value) return } - if let instance = value as? FileHandle { pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -485,11 +518,13 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( + data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( + data: data, pigeonRegistrar: pigeonRegistrar) } } @@ -510,7 +545,8 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. @@ -528,9 +564,15 @@ protocol CrossFileDarwinApi { class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -545,7 +587,10 @@ class CrossFileDarwinApiSetup { } else { tryCreateBookmarkedUrlChannel.setMessageHandler(nil) } - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let isReadableFileChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -560,7 +605,9 @@ class CrossFileDarwinApiSetup { } else { isReadableFileChannel.setMessageHandler(nil) } - let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let fileExistsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileExistsChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -575,7 +622,10 @@ class CrossFileDarwinApiSetup { } else { fileExistsChannel.setMessageHandler(nil) } - let fileIsDirectoryChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let fileIsDirectoryChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileIsDirectoryChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -590,7 +640,10 @@ class CrossFileDarwinApiSetup { } else { fileIsDirectoryChannel.setMessageHandler(nil) } - let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let fileModificationDateChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileModificationDateChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -605,7 +658,9 @@ class CrossFileDarwinApiSetup { } else { fileModificationDateChannel.setMessageHandler(nil) } - let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let fileSizeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileSizeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -620,7 +675,9 @@ class CrossFileDarwinApiSetup { } else { fileSizeChannel.setMessageHandler(nil) } - let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let listChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { listChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -639,29 +696,40 @@ class CrossFileDarwinApiSetup { } protocol PigeonApiDelegateFileHandle { func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? - func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws -> Int64 + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) + throws -> FlutterStandardTypedData? + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws + -> FlutterStandardTypedData? + func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws + -> Int64 func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } protocol PigeonApiProtocolFileHandle { } -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateFileHandle - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { + init( + pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateFileHandle + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let forReadingFromUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl", binaryMessenger: binaryMessenger, codec: codec) + let forReadingFromUrlChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { forReadingFromUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -669,8 +737,8 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { let urlArg = args[1] as! String do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( -try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), -withIdentifier: pigeonIdentifierArg) + try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -679,14 +747,17 @@ withIdentifier: pigeonIdentifierArg) } else { forReadingFromUrlChannel.setMessageHandler(nil) } - let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) + let readUpToCountChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readUpToCountChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let countArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + let result = try api.pigeonDelegate.readUpToCount( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -695,13 +766,16 @@ withIdentifier: pigeonIdentifierArg) } else { readUpToCountChannel.setMessageHandler(nil) } - let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) + let readToEndChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readToEndChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.readToEnd( + pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -710,14 +784,17 @@ withIdentifier: pigeonIdentifierArg) } else { readToEndChannel.setMessageHandler(nil) } - let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) + let seekChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { seekChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let offsetArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) + let result = try api.pigeonDelegate.seek( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -726,7 +803,9 @@ withIdentifier: pigeonIdentifierArg) } else { seekChannel.setMessageHandler(nil) } - let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) + let closeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { closeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -744,21 +823,25 @@ withIdentifier: pigeonIdentifierArg) } ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: FileHandle, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift index 1fdfcdff529c..c3b8b3461b3f 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift @@ -1,17 +1,17 @@ #if os(iOS) -import Flutter -import UIKit + import Flutter + import UIKit #elseif os(macOS) -import Cocoa -import FlutterMacOS + import Cocoa + import FlutterMacOS #endif public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { #if os(iOS) - let messenger = registrar.messenger() + let messenger = registrar.messenger() #elseif os(macOS) - let messenger = registrar.messenger + let messenger = registrar.messenger #endif let channel = FlutterMethodChannel(name: "cross_file_darwin", binaryMessenger: messenger) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift new file mode 100644 index 000000000000..e73dff963d29 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift @@ -0,0 +1,38 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +/// ProxyApi implementation for `FileHandle`. +/// +/// This class may handle instantiating native object instances that are attached to a Dart instance +/// or handle method calls on the associated native class or an instance of that class. +class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle { + return FileHandle(url: url) + } + + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) + throws -> FlutterStandardTypedData? + { + return pigeonInstance.readUpToCount(count: count) + } + + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws + -> FlutterStandardTypedData? + { + return pigeonInstance.readToEnd() + } + + func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws + -> Int64 + { + return pigeonInstance.seek(offset: offset) + } + + func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { + pigeonInstance.close() + } + +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift new file mode 100644 index 000000000000..8b9b5b043511 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift @@ -0,0 +1,87 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import XCTest + +@testable import cross_file_darwin + +class FileHandleTests: XCTestCase { + func testForReadingFromUrl() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = try? api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: "myString") + XCTAssertNotNil(instance) + } + + func testReadUpToCount() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = TestFileHandle() + let count = 0 + let value = try? api.pigeonDelegate.readUpToCount( + pigeonApi: api, pigeonInstance: instance, count: count) + + XCTAssertEqual(instance.readUpToCountArgs, [count]) + XCTAssertEqual(value, instance.readUpToCount(count: count)) + } + + func testReadToEnd() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = TestFileHandle() + let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.readToEndCalled) + XCTAssertEqual(value, instance.readToEnd()) + } + + func testSeek() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = TestFileHandle() + let offset = 0 + let value = try? api.pigeonDelegate.seek( + pigeonApi: api, pigeonInstance: instance, offset: offset) + + XCTAssertEqual(instance.seekArgs, [offset]) + XCTAssertEqual(value, instance.seek(offset: offset)) + } + + func testClose() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let instance = TestFileHandle() + try? api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: instance) + + XCTAssertTrue(instance.closeCalled) + } + +} +class TestFileHandle: FileHandle { + var readUpToCountArgs: [AnyHashable?]? = nil + var readToEndCalled = false + var seekArgs: [AnyHashable?]? = nil + var closeCalled = false + + override func readUpToCount() { + readUpToCountArgs = [count] + return byteArrayOf(0xA1.toByte()) + } + override func readToEnd() { + readToEndCalled = true + } + override func seek() { + seekArgs = [offset] + return 0 + } + override func close() { + closeCalled = true + } +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift index 74d18bc464f9..749eeb986e79 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift @@ -2,7 +2,6 @@ import Flutter import UIKit import XCTest - @testable import cross_file_darwin // This demonstrates a simple unit test of the Swift portion of this plugin's implementation. diff --git a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift index b38c13977aaf..bd120c3c0b5d 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift +++ b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift @@ -2,7 +2,6 @@ import Cocoa import FlutterMacOS import XCTest - @testable import cross_file_darwin // This demonstrates a simple unit test of the Swift portion of this plugin's implementation. @@ -18,8 +17,9 @@ class RunnerTests: XCTestCase { let resultExpectation = expectation(description: "result block must be called.") plugin.handle(call) { result in - XCTAssertEqual(result as! String, - "macOS " + ProcessInfo.processInfo.operatingSystemVersionString) + XCTAssertEqual( + result as! String, + "macOS " + ProcessInfo.processInfo.operatingSystemVersionString) resultExpectation.fulfill() } waitForExpectations(timeout: 1) diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 2acef346003f..6e2a72192973 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' + show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -20,7 +21,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -29,6 +34,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -40,7 +46,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [FileHandle.forReadingFromUrl]. static FileHandle Function({required String url})? - fileHandle_forReadingFromUrl; + fileHandle_forReadingFromUrl; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { @@ -60,7 +66,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -130,9 +136,10 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; + final Map> + _weakInstances = >{}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -145,7 +152,8 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = + _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -153,8 +161,12 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager, + ); + FileHandle.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -171,8 +183,9 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference( + instance, + ); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -233,15 +246,21 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference( + int identifier, + ) { + final PigeonInternalProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance + .pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = + WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -263,7 +282,10 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + void addHostCreatedInstance( + PigeonInternalProxyApiBaseClass instance, + int identifier, + ) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -292,7 +314,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -305,28 +327,35 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.', + ); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + assert( + arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', + ); try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); + (instanceManager ?? PigeonInstanceManager.instance).remove( + arg_identifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -341,8 +370,9 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -385,30 +415,30 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference( + readValue(buffer)! as int, + ); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -435,9 +465,13 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + CrossFileDarwinApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -445,13 +479,16 @@ class CrossFileDarwinApi { final String pigeonVar_messageChannelSuffix; Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -467,13 +504,16 @@ class CrossFileDarwinApi { } Future isReadableFile(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -494,13 +534,16 @@ class CrossFileDarwinApi { } Future fileExists(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -521,13 +564,16 @@ class CrossFileDarwinApi { } Future fileIsDirectory(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -548,13 +594,16 @@ class CrossFileDarwinApi { } Future fileModificationDate(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -570,13 +619,16 @@ class CrossFileDarwinApi { } Future fileSize(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -592,13 +644,16 @@ class CrossFileDarwinApi { } Future> list(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -618,6 +673,7 @@ class CrossFileDarwinApi { } } } + class FileHandle extends PigeonInternalProxyApiBaseClass { factory FileHandle.forReadingFromUrl({ BinaryMessenger? pigeon_binaryMessenger, @@ -640,8 +696,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String url, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -652,8 +708,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier, url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, url], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -691,39 +748,46 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + FileHandle.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -741,8 +805,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, count]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, count], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -768,8 +833,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -795,8 +861,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, offset]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, offset], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -827,8 +894,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -851,4 +919,3 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { ); } } - From 677c89039ba68b1e87f55582a53ed876381f2010 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 16 Jan 2026 20:16:02 -0500 Subject: [PATCH 094/398] add file --- .../Classes/apiImplementations/CrossFileDarwinApiImpl.swift | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift new file mode 100644 index 000000000000..14abbcf71b10 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -0,0 +1,5 @@ +// +// Created by Maurice Parrish on 1/16/26. +// + +import Foundation From 9e51db5675f04c545f46a41d607e20bd777a3df6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:05:39 -0500 Subject: [PATCH 095/398] ios impl hopefully --- .../Classes/CrossFileDarwinApis.g.swift | 16 ++- .../Classes/CrossFileDarwinPlugin.swift | 42 +++++--- .../darwin/Classes/ProxyAPIDelegate.swift | 23 ++++ .../CrossFileDarwinApiImpl.swift | 65 ++++++++++- .../FileHandleProxyAPIDelegate.swift | 41 +++++-- .../lib/src/cross_file_darwin_apis.g.dart | 101 +++++++----------- .../src/darwin_scoped_storage_cross_file.dart | 8 +- .../pigeons/cross_file_darwin_apis.dart | 5 +- .../proxies/FileManagerProxyAPIDelegate.swift | 1 - 9 files changed, 197 insertions(+), 105 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift index 90ea47205237..ed129c70a053 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -695,13 +695,12 @@ class CrossFileDarwinApiSetup { } } protocol PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle? func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws - -> Int64 func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } @@ -733,13 +732,10 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { if let api = api { forReadingFromUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let pigeonIdentifierArg = args[0] as! Int64 - let urlArg = args[1] as! String + let urlArg = args[0] as! String do { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), - withIdentifier: pigeonIdentifierArg) - reply(wrapResult(nil)) + let result = try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg) + reply(wrapResult(result)) } catch { reply(wrapError(error)) } @@ -793,9 +789,9 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { let pigeonInstanceArg = args[0] as! FileHandle let offsetArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.seek( + try api.pigeonDelegate.seek( pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) - reply(wrapResult(result)) + reply(wrapResult(nil)) } catch { reply(wrapError(error)) } diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift index c3b8b3461b3f..98c682d267e7 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #if os(iOS) import Flutter import UIKit @@ -7,6 +11,14 @@ #endif public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { + var proxyApiRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar? + + init(binaryMessenger: FlutterBinaryMessenger) { + proxyApiRegistrar = CrossFileDarwinApisPigeonProxyApiRegistrar( + binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) + proxyApiRegistrar?.setUp() + } + public static func register(with registrar: FlutterPluginRegistrar) { #if os(iOS) let messenger = registrar.messenger() @@ -14,23 +26,21 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { let messenger = registrar.messenger #endif - let channel = FlutterMethodChannel(name: "cross_file_darwin", binaryMessenger: messenger) - let instance = CrossFileDarwinPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) + CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: CrossFileDarwinApiImpl()) + let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger) + registrar.publish(plugin) } - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - switch call.method { - case "getPlatformVersion": - #if os(iOS) - result("iOS " + UIDevice.current.systemVersion) - #elseif os(macOS) - result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString) - #else - result(FlutterMethodNotImplemented) - #endif - default: - result(FlutterMethodNotImplemented) - } + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + #if os(iOS) + let messenger = registrar.messenger() + #elseif os(macOS) + let messenger = registrar.messenger + #endif + + CrossFileDarwinApiSetup.setUp(binaryMessenger: registrar.messenger(), api: nil) + proxyApiRegistrar!.ignoreCallsToDart = true + proxyApiRegistrar!.tearDown() + proxyApiRegistrar = nil } } diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift new file mode 100644 index 000000000000..c868ddc53f67 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift @@ -0,0 +1,23 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +/// Implementation of `CrossFileDarwinApisPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation +/// and any additional resources needed by an implementation. +open class ProxyApiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { + /// Creates an error when the constructor of a class returns null. + func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { + return PigeonError( + code: "ConstructorReturnedNullError", + message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", + details: nil) + } + + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiFileHandle + { + return PigeonApiFileHandle(pigeonRegistrar: registrar, delegate: FileHandleProxyAPIDelegate()) + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index 14abbcf71b10..68365402175e 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -1,5 +1,64 @@ -// -// Created by Maurice Parrish on 1/16/26. -// +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +import Flutter import Foundation + +class CrossFileDarwinApiImpl: CrossFileDarwinApi { + func tryCreateBookmarkedUrl(url: String) throws -> String? { + let nativeUrl = URL(string: url) + if let url = nativeUrl { + if url.startAccessingSecurityScopedResource() { + let data = try url.bookmarkData( + options: [], + includingResourceValuesForKeys: nil, + relativeTo: nil + ) + + var isStale: Bool = true + let url: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) + + if isStale { + return url.absoluteString + } + } + } + + return nil + } + + func isReadableFile(url: String) throws -> Bool { + return FileManager.default.isReadableFile(atPath: url) + } + + func fileExists(url: String) throws -> Bool { + return FileManager.default.fileExists(atPath: url) + } + + func fileIsDirectory(url: String) throws -> Bool { + var isDirectory: ObjCBool = true + return FileManager.default.fileExists(atPath: url, isDirectory: &isDirectory) + && isDirectory.boolValue + } + + func fileModificationDate(url: String) throws -> Int64? { + let attributes: NSDictionary = + try FileManager.default.attributesOfItem(atPath: url) as NSDictionary + if let date = attributes.fileModificationDate() { + return Int64(date.timeIntervalSince1970 * 1000) + } + + return nil + } + + func fileSize(url: String) throws -> Int64? { + let attributes: NSDictionary = + try FileManager.default.attributesOfItem(atPath: url) as NSDictionary + return Int64(attributes.fileSize()) + } + + func list(url: String) throws -> [String] { + return try FileManager.default.contentsOfDirectory(atPath: url) + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift index e73dff963d29..9f2b02bb0d73 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Flutter import Foundation /// ProxyApi implementation for `FileHandle`. @@ -9,30 +10,50 @@ import Foundation /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle { - return FileHandle(url: url) + func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle? { + return FileHandle(forReadingAtPath: url) } func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? { - return pigeonInstance.readUpToCount(count: count) + var data: Data? + if #available(iOS 13.4, *) { + data = try pigeonInstance.read(upToCount: Int(count)) + } else { + data = pigeonInstance.readData(ofLength: Int(count)) + } + + if let data = data { + return FlutterStandardTypedData(bytes: data) + } + + return nil } func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? { - return pigeonInstance.readToEnd() + var bytes: Data? + if #available(iOS 13.4, *) { + bytes = try pigeonInstance.readToEnd() + } else { + bytes = pigeonInstance.readDataToEndOfFile() + } + + if let bytes = bytes { + return FlutterStandardTypedData(bytes: bytes) + } + + return nil } - func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws - -> Int64 - { - return pigeonInstance.seek(offset: offset) + func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws { + let convertedOffset = UInt64(exactly: offset)! + try pigeonInstance.seek(toOffset: convertedOffset) } func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { - pigeonInstance.close() + try pigeonInstance.close() } - } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 6e2a72192973..b5961b1cc9eb 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -45,8 +45,7 @@ List wrapResponse({ @visibleForTesting class PigeonOverrides { /// Overrides [FileHandle.forReadingFromUrl]. - static FileHandle Function({required String url})? - fileHandle_forReadingFromUrl; + static Future Function(String)? fileHandle_forReadingFromUrl; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { @@ -675,58 +674,6 @@ class CrossFileDarwinApi { } class FileHandle extends PigeonInternalProxyApiBaseClass { - factory FileHandle.forReadingFromUrl({ - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - required String url, - }) { - if (PigeonOverrides.fileHandle_forReadingFromUrl != null) { - return PigeonOverrides.fileHandle_forReadingFromUrl!(url: url); - } - return FileHandle.pigeon_forReadingFromUrl( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - url: url, - ); - } - - @protected - FileHandle.pigeon_forReadingFromUrl({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - required String url, - }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, url], - ); - () async { - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - }(); - } - /// Constructs [FileHandle] without creating the associated native object. /// /// This should only be used by subclasses created by this library or to @@ -794,6 +741,43 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } + static Future forReadingFromUrl( + String url, { + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) async { + if (PigeonOverrides.fileHandle_forReadingFromUrl != null) { + return PigeonOverrides.fileHandle_forReadingFromUrl!(url); + } + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return (pigeonVar_replyList[0] as FileHandle?); + } + } + Future readUpToCount(int count) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; @@ -850,7 +834,7 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } - Future seek(int offset) async { + Future seek(int offset) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -873,13 +857,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { message: pigeonVar_replyList[1] as String?, details: pigeonVar_replyList[2], ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); } else { - return (pigeonVar_replyList[0] as int?)!; + return; } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 0566d4ed8548..cfb4ffe11ef9 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -112,7 +112,11 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { int bytesToRead = (end ?? fileLength) - (start ?? 0); assert(bytesToRead >= 0); - final handle = FileHandle.forReadingFromUrl(url: params.uri); + final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); + if (handle == null) { + throw UnsupportedError('Cannot access file length.'); + } + try { if (start != null && start > 0) { await handle.seek(start); @@ -140,7 +144,7 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { @override Future readAsBytes() async { - final handle = FileHandle.forReadingFromUrl(url: params.uri); + final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); try { final Uint8List? bytes = await handle.readToEnd(); if (bytes == null) { diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index f709bb882dfc..c1a90aa3167e 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -32,13 +32,14 @@ abstract class CrossFileDarwinApi { @ProxyApi() abstract class FileHandle { - FileHandle.forReadingFromUrl(String url); + @static + FileHandle? forReadingFromUrl(String url); Uint8List? readUpToCount(int count); Uint8List? readToEnd(); - int seek(int offset); + void seek(int offset); void close(); } diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift index 781a9ebdb156..5ed645924158 100644 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift @@ -44,5 +44,4 @@ class FileManagerProxyAPIDelegate: PigeonApiDelegateFileManager { try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary return Int64(attributes.fileSize()) } - } From f92d3c1655519c0796127d88b000326fa4d994a1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:29:28 -0500 Subject: [PATCH 096/398] it buildssssss --- ...darwin_scoped_storage_cross_directory.dart | 12 +- .../src/darwin_scoped_storage_cross_file.dart | 120 +----------------- 2 files changed, 15 insertions(+), 117 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 484a519ee39a..fe6ec9bfd0a4 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -55,6 +55,16 @@ base class DarwinScopedStorageXDirectory @override Stream list(ListParams params) async* { - // list files + for (final String url in await this.params.api.list(this.params.uri)) { + if (await this.params.api.fileIsDirectory(url)) { + yield DarwinScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams(uri: url), + ); + } else { + yield DarwinScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: url), + ); + } + } } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index cfb4ffe11ef9..48b828e3a60a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -57,25 +57,6 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { DarwinScopedStorageXFileCreationParams(uri: bookmarkedUrl), ) : null; - // final URL? url = await _originalUrl; - // if (url case URL url) { - // final bool canRead = await url.startAccessingSecurityScopedResource(); - // if (canRead) { - // try { - // final Uint8List? bookmarkData = await url.bookmarkData([], [], null); - // if (bookmarkData case Uint8List bookmarkData) { - // final URLResolvingBookmarkDataResponse response = await URL - // .resolvingBookmarkData(bookmarkData, [], null); - // if (response.isStale) { - // print('STALE'); - // return null; - // } - // return response.url; - // } - // } finally { - // await url.stopAccessingSecurityScopedResource(); - // } - // } } @override @@ -145,6 +126,10 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { @override Future readAsBytes() async { final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); + if (handle == null) { + throw UnsupportedError('Can not create file handle'); + } + try { final Uint8List? bytes = await handle.readToEnd(); if (bytes == null) { @@ -161,101 +146,4 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { Future readAsString({Encoding encoding = utf8}) async { return encoding.decodeStream(openRead()); } - - // late final Future _originalUrl = URL.fileURLWithPath(params.path); - // - // late final Future _bookmarkUrl = () async { - // final URL? url = await _originalUrl; - // if (url case URL url) { - // final bool canRead = await url.startAccessingSecurityScopedResource(); - // if (canRead) { - // try { - // final Uint8List? bookmarkData = await url.bookmarkData([], [], null); - // if (bookmarkData case Uint8List bookmarkData) { - // final URLResolvingBookmarkDataResponse response = await URL - // .resolvingBookmarkData(bookmarkData, [], null); - // if (response.isStale) { - // print('STALE'); - // return null; - // } - // return response.url; - // } - // } finally { - // await url.stopAccessingSecurityScopedResource(); - // } - // } - // } - // - // return null; - // }(); - // - // @override - // Future canRead() async { - // final URL? bookmarkUrl = await _bookmarkUrl; - // if (bookmarkUrl case URL bookmarkUrl) { - // return FileManager.defaultManager.isReadableFile( - // await bookmarkUrl.path(), - // ); - // } - // - // return false; - // } - // - // @override - // Future exists() async { - // final URL? bookmarkUrl = await _bookmarkUrl; - // if (bookmarkUrl case URL bookmarkUrl) { - // return FileManager.defaultManager.fileExists(await bookmarkUrl.path()); - // } - // - // return false; - // } - // - // @override - // Future lastModified() async { - // final URL? bookmarkUrl = await _bookmarkUrl; - // if (bookmarkUrl case URL bookmarkUrl) { - // final int? lastModifiedSinceEpoch = await FileManager.defaultManager - // .fileModificationDate(await bookmarkUrl.path()); - // if (lastModifiedSinceEpoch case int lastModifiedSinceEpoch) { - // return DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch); - // } - // } - // - // throw UnsupportedError('cant read: ${params.path}'); - // } - // - // @override - // Future length() async { - // final URL? bookmarkUrl = await _bookmarkUrl; - // if (bookmarkUrl case URL bookmarkUrl) { - // final int? fileSize = await FileManager.defaultManager.fileSize( - // await bookmarkUrl.path(), - // ); - // if (fileSize case int fileSize) { - // return fileSize; - // } - // } - // - // throw UnsupportedError('cant read: ${params.path}'); - // } - - // @override - // Stream> openRead([int? start, int? end]) async* { - // if (await _bookmarkUrl case URL url) { - // final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); - // try { - // Uint8List? bytes = await fileHandle.readUpToCount(4 * 1024); - // while (bytes != null && bytes.isNotEmpty) { - // yield bytes; - // // TODO: this is only supported on ios 13.4 - // bytes = await fileHandle.readUpToCount(4 * 1024); - // } - // } finally { - // await fileHandle.close(); - // } - // } else { - // throw UnsupportedError('Cant access bytes to file: ${params.path}'); - // } - // } } From 3e8918c1624ca4b63a7691ba847fd1e95d5bb9e3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:02:17 -0500 Subject: [PATCH 097/398] update old ios code --- .../ios/Flutter/AppFrameworkInfo.plist | 2 - .../contents.xcworkspacedata | 3 + .../example/ios/Runner/AppDelegate.swift | 7 +- .../example/ios/Runner/Info.plist | 29 ++++- .../cross_file_ios/example/lib/main.dart | 102 +++++++++++++++--- .../cross_file_ios/example/pubspec.yaml | 79 +++----------- .../cross_file_ios/lib/cross_file_ios.dart | 2 +- .../lib/src/cross_file_ios.dart | 6 +- .../lib/src/ios_cross_file.dart | 21 ++-- 9 files changed, 150 insertions(+), 101 deletions(-) diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist b/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist index 1dc6cf7652ba..391a902b2beb 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 13.0 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift b/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift index 626664468b89..c30b367ec0a9 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift @@ -2,12 +2,15 @@ import Flutter import UIKit @main -@objc class AppDelegate: FlutterAppDelegate { +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { - GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } } diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist b/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist index df7346c71700..670b70bea7f6 100644 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist +++ b/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -24,6 +26,29 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + FlutterSceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -41,9 +66,5 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - diff --git a/packages/cross_file/cross_file_ios/example/lib/main.dart b/packages/cross_file/cross_file_ios/example/lib/main.dart index e04612320022..49a2ec5d16c0 100644 --- a/packages/cross_file/cross_file_ios/example/lib/main.dart +++ b/packages/cross_file/cross_file_ios/example/lib/main.dart @@ -1,32 +1,104 @@ -import 'package:flutter/material.dart'; -import 'dart:async'; +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -import 'package:flutter/services.dart'; import 'package:cross_file_ios/cross_file_ios.dart'; +import 'package:file_selector_ios/file_selector_ios.dart'; +import 'package:flutter/material.dart'; +import 'package:mime/mime.dart' as mime; void main() { - runApp(const MyApp()); + runApp(const MaterialApp(home: FileOpenScreen())); } -class MyApp extends StatefulWidget { - const MyApp({super.key}); +/// Example screen to open a file selector and display it. +class FileOpenScreen extends StatelessWidget { + /// Constructs a [FileOpenScreen]. + const FileOpenScreen({super.key}); + + Future _openFile(BuildContext context) async { + final IOSXFile? file = await FileSelectorIOS().openFile2(); + + if (!context.mounted) { + return; + } + + print(file?.params.uri); + + if (file case final IOSXFile file) { + switch (mime.lookupMimeType(file.params.uri)) { + case final String mimeType when mimeType.startsWith('text'): + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(file), + ); + case final String mimeType when mimeType.startsWith('image'): + case final String mimeType when mimeType.startsWith('application'): + case null: + debugPrint('Unsupported file type: ${file.params.uri}'); + return; + } + } + } @override - State createState() => _MyAppState(); + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a File'), + backgroundColor: Colors.blue, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ], + ), + ), + ); + } } -class _MyAppState extends State { +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.file, {super.key}); + + /// The file. + final IOSXFile file; + @override Widget build(BuildContext context) { - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Plugin example app'), - ), - body: Center( - child: Text('Running on: \n'), + return AlertDialog( + title: Text(file.params.uri), + content: Scrollbar( + child: SingleChildScrollView( + child: FutureBuilder( + future: file.readAsString(), + builder: (_, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!); + } else { + return const CircularProgressIndicator(); + } + }, + ), ), ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], ); } } diff --git a/packages/cross_file/cross_file_ios/example/pubspec.yaml b/packages/cross_file/cross_file_ios/example/pubspec.yaml index 6d4b97118544..92583c1c9d25 100644 --- a/packages/cross_file/cross_file_ios/example/pubspec.yaml +++ b/packages/cross_file/cross_file_ios/example/pubspec.yaml @@ -1,85 +1,32 @@ name: cross_file_ios_example -description: "Demonstrates how to use the cross_file_ios plugin." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev +description: "Demonstrates how to use the cross_file_darwin plugin." +publish_to: 'none' environment: - sdk: ^3.10.0-200.0.dev + sdk: ^3.9.0 + flutter: ">=3.35.0" -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: - flutter: - sdk: flutter - cross_file_ios: # When depending on this package from a real application you should use: - # cross_file_ios: ^x.y.z + # cross_file_darwin: ^x.y.z # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 + file_selector_ios: + path: ../../../file_selector/file_selector_ios + flutter: + sdk: flutter + mime: ^2.0.0 + video_player: ^2.8.6 dev_dependencies: - integration_test: - sdk: flutter flutter_test: sdk: flutter + integration_test: + sdk: flutter - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. - flutter_lints: ^6.0.0 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. uses-material-design: true - - # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart index d833bb69252e..b30dfb339087 100644 --- a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart +++ b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart @@ -1,4 +1,4 @@ export 'src/ios_cross_file.dart'; export 'src/cross_file_ios.dart'; export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show PlatformSharedStorageXFileCreationParams; + show PlatformScopedStorageXFileCreationParams; diff --git a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart index 881b156c43bd..f9a0486c7d27 100644 --- a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart +++ b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart @@ -11,13 +11,13 @@ final class CrossFileIOS extends CrossFilePlatform { @override IOSXFile createPlatformXFile(PlatformXFileCreationParams params) { return IOSXFile( - PlatformSharedStorageXFileCreationParams(path: params.path), + PlatformScopedStorageXFileCreationParams(uri: params.uri), ); } @override - PlatformSharedStorageXFile createPlatformSharedStorageXFile( - PlatformSharedStorageXFileCreationParams params, + PlatformScopedStorageXFile createPlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, ) { return IOSXFile(params); } diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart index 0b7542c7fb7e..e09207c59693 100644 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart @@ -6,10 +6,10 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart // Note for me: Will probs need a `static Future method(Uint8List bookmarkData` method // instead to create persistent file. -base class IOSXFile extends PlatformSharedStorageXFile { +base class IOSXFile extends PlatformScopedStorageXFile { IOSXFile(super.params) : super.implementation(); - late final Future _originalUrl = URL.fileURLWithPath(params.path); + late final Future _originalUrl = URL.fileURLWithPath(params.uri); late final Future _bookmarkUrl = () async { final URL? url = await _originalUrl; @@ -22,7 +22,6 @@ base class IOSXFile extends PlatformSharedStorageXFile { final URLResolvingBookmarkDataResponse response = await URL .resolvingBookmarkData(bookmarkData, [], null); if (response.isStale) { - print('STALE'); return null; } return response.url; @@ -69,7 +68,7 @@ base class IOSXFile extends PlatformSharedStorageXFile { } } - throw UnsupportedError('cant read: ${params.path}'); + throw UnsupportedError('cant read: ${params.uri}'); } @override @@ -84,7 +83,7 @@ base class IOSXFile extends PlatformSharedStorageXFile { } } - throw UnsupportedError('cant read: ${params.path}'); + throw UnsupportedError('cant read: ${params.uri}'); } @override @@ -94,7 +93,7 @@ base class IOSXFile extends PlatformSharedStorageXFile { } @override - Stream> openRead([int? start, int? end]) async* { + Stream openRead([int? start, int? end]) async* { if (await _bookmarkUrl case URL url) { final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); try { @@ -108,7 +107,7 @@ base class IOSXFile extends PlatformSharedStorageXFile { await fileHandle.close(); } } else { - throw UnsupportedError('Cant access bytes to file: ${params.path}'); + throw UnsupportedError('Cant access bytes to file: ${params.uri}'); } } @@ -127,11 +126,17 @@ base class IOSXFile extends PlatformSharedStorageXFile { } } - throw UnsupportedError('Cant access bytes to file: ${params.path}'); + throw UnsupportedError('Cant access bytes to file: ${params.uri}'); } @override Future readAsString({Encoding encoding = utf8}) async { return encoding.decode(await readAsBytes()); } + + @override + Future name() { + // TODO: implement name + throw UnimplementedError(); + } } From 21fa116fd7fbc889a1fcab1ef8bf833a7c392078 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:10:40 -0500 Subject: [PATCH 098/398] fix impl --- .../Classes/apiImplementations/CrossFileDarwinApiImpl.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index 68365402175e..4eb3c00e5f55 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -19,7 +19,7 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { var isStale: Bool = true let url: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - if isStale { + if (!isStale) { return url.absoluteString } } From 1cb4c116978835e3ccbd74d3e67e9d3fbf636de3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 11:25:45 -0500 Subject: [PATCH 099/398] use file url and defer --- .../CrossFileDarwinApiImpl.swift | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index 4eb3c00e5f55..7325b2692425 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -7,21 +7,21 @@ import Foundation class CrossFileDarwinApiImpl: CrossFileDarwinApi { func tryCreateBookmarkedUrl(url: String) throws -> String? { - let nativeUrl = URL(string: url) - if let url = nativeUrl { - if url.startAccessingSecurityScopedResource() { - let data = try url.bookmarkData( - options: [], - includingResourceValuesForKeys: nil, - relativeTo: nil - ) + let nativeUrl = URL(fileURLWithPath: url) + if nativeUrl.startAccessingSecurityScopedResource() { + defer { nativeUrl.stopAccessingSecurityScopedResource() } + + let data = try nativeUrl.bookmarkData( + options: [], + includingResourceValuesForKeys: nil, + relativeTo: nil + ) - var isStale: Bool = true - let url: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) + var isStale: Bool = true + let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - if (!isStale) { - return url.absoluteString - } + if (!isStale) { + return bookmarkedUrl.path } } From 601ee9501ed4ab72d35ef6cef4e95451817502f0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:35:09 -0500 Subject: [PATCH 100/398] update checking if thing exists --- .../Classes/CrossFileDarwinApis.g.swift | 324 +++++++++-------- .../CrossFileDarwinApiImpl.swift | 6 +- .../lib/src/cross_file_darwin_apis.g.dart | 344 ++++++++---------- ...darwin_scoped_storage_cross_directory.dart | 10 +- .../src/darwin_scoped_storage_cross_file.dart | 17 +- .../pigeons/cross_file_darwin_apis.dart | 10 +- 6 files changed, 356 insertions(+), 355 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift index ed129c70a053..d192813e5a1e 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -59,9 +59,7 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError( - code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", - details: "") + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -73,12 +71,76 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +func deepEqualsCrossFileDarwinApis(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true + + case (nil, _), (_, nil): + return false + + case is (Void, Void): + return true + + case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): + return cleanLhsHashable == cleanRhsHashable + + case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): + guard cleanLhsArray.count == cleanRhsArray.count else { return false } + for (index, element) in cleanLhsArray.enumerated() { + if !deepEqualsCrossFileDarwinApis(element, cleanRhsArray[index]) { + return false + } + } + return true + + case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } + for (key, cleanLhsValue) in cleanLhsDictionary { + guard cleanRhsDictionary.index(forKey: key) != nil else { return false } + if !deepEqualsCrossFileDarwinApis(cleanLhsValue, cleanRhsDictionary[key]!) { + return false + } + } + return true + + default: + // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue. + return false + } +} + +func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { + if let valueList = value as? [AnyHashable] { + for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } + return + } + + if let valueDict = value as? [AnyHashable: AnyHashable] { + for key in valueDict.keys { + hasher.combine(key) + deepHashCrossFileDarwinApis(value: valueDict[key]!, hasher: &hasher) + } + return + } + + if let hashableValue = value as? AnyHashable { + hasher.combine(hashableValue.hashValue) + } + + return hasher.combine(String(describing: value)) +} + + /// Handles the callback when an object is deallocated. protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. func onDeinit(identifier: Int64) } + // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -94,18 +156,14 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, - delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( - identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = - objc_getAssociatedObject(instance, associatedObjectKey) - as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -117,6 +175,7 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } + /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -220,8 +279,7 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach( - to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -302,6 +360,7 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } + private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -314,15 +373,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, - instanceManager: CrossFileDarwinApisPigeonInstanceManager? - ) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", - binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -337,9 +390,7 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", - binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -355,13 +406,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference( - identifier identifierArg: Int64, completion: @escaping (Result) -> Void - ) { - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -381,8 +428,7 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) - -> PigeonApiFileHandle + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -395,15 +441,12 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: - CrossFileDarwinApisPigeonInternalFinalizerDelegate - { + private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -417,9 +460,7 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init( - binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - ) { + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -428,25 +469,18 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiFileHandle.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: - FlutterStandardReaderWriter -{ +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: - CrossFileDarwinApisPigeonCodecReader - { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -470,9 +504,7 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: - CrossFileDarwinApisPigeonCodecWriter - { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -481,26 +513,24 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] - || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String - { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { super.writeValue(value) return } + if let instance = value as? FileHandle { pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) return } - if let instance = value as AnyObject?, - pigeonRegistrar.instanceManager.containsInstance(instance) + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -518,20 +548,63 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( - data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( - data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + } +} + +/// Generated class from Pigeon that represents data sent in messages. +struct FileExistsResult: Hashable { + var exists: Bool + var isDirectory: Bool + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> FileExistsResult? { + let exists = pigeonVar_list[0] as! Bool + let isDirectory = pigeonVar_list[1] as! Bool + + return FileExistsResult( + exists: exists, + isDirectory: isDirectory + ) + } + func toList() -> [Any?] { + return [ + exists, + isDirectory, + ] + } + static func == (lhs: FileExistsResult, rhs: FileExistsResult) -> Bool { + return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashCrossFileDarwinApis(value: toList(), hasher: &hasher) } } private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + return FileExistsResult.fromList(self.readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } } private class CrossFileDarwinApisPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? FileExistsResult { + super.writeByte(129) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } } private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderWriter { @@ -545,16 +618,14 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec( - readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol CrossFileDarwinApi { func tryCreateBookmarkedUrl(url: String) throws -> String? func isReadableFile(url: String) throws -> Bool - func fileExists(url: String) throws -> Bool - func fileIsDirectory(url: String) throws -> Bool + func fileExists(url: String) throws -> FileExistsResult func fileModificationDate(url: String) throws -> Int64? func fileSize(url: String) throws -> Int64? func list(url: String) throws -> [String] @@ -564,15 +635,9 @@ protocol CrossFileDarwinApi { class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp( - binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, - messageChannelSuffix: String = "" - ) { + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -587,10 +652,7 @@ class CrossFileDarwinApiSetup { } else { tryCreateBookmarkedUrlChannel.setMessageHandler(nil) } - let isReadableFileChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -605,9 +667,7 @@ class CrossFileDarwinApiSetup { } else { isReadableFileChannel.setMessageHandler(nil) } - let fileExistsChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileExistsChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -622,28 +682,7 @@ class CrossFileDarwinApiSetup { } else { fileExistsChannel.setMessageHandler(nil) } - let fileIsDirectoryChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileIsDirectoryChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileIsDirectory(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileIsDirectoryChannel.setMessageHandler(nil) - } - let fileModificationDateChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileModificationDateChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -658,9 +697,7 @@ class CrossFileDarwinApiSetup { } else { fileModificationDateChannel.setMessageHandler(nil) } - let fileSizeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileSizeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -675,9 +712,7 @@ class CrossFileDarwinApiSetup { } else { fileSizeChannel.setMessageHandler(nil) } - let listChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { listChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -696,10 +731,8 @@ class CrossFileDarwinApiSetup { } protocol PigeonApiDelegateFileHandle { func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle? - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) - throws -> FlutterStandardTypedData? - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws - -> FlutterStandardTypedData? + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } @@ -707,28 +740,20 @@ protocol PigeonApiDelegateFileHandle { protocol PigeonApiProtocolFileHandle { } -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateFileHandle - init( - pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, - delegate: PigeonApiDelegateFileHandle - ) { + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle? - ) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let forReadingFromUrlChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl", - binaryMessenger: binaryMessenger, codec: codec) + let forReadingFromUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl", binaryMessenger: binaryMessenger, codec: codec) if let api = api { forReadingFromUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -743,17 +768,14 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { forReadingFromUrlChannel.setMessageHandler(nil) } - let readUpToCountChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", - binaryMessenger: binaryMessenger, codec: codec) + let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) if let api = api { readUpToCountChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let countArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.readUpToCount( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -762,16 +784,13 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { readUpToCountChannel.setMessageHandler(nil) } - let readToEndChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", - binaryMessenger: binaryMessenger, codec: codec) + let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) if let api = api { readToEndChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.readToEnd( - pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -780,17 +799,14 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { readToEndChannel.setMessageHandler(nil) } - let seekChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", - binaryMessenger: binaryMessenger, codec: codec) + let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) if let api = api { seekChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let offsetArg = args[1] as! Int64 do { - try api.pigeonDelegate.seek( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) + try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -799,9 +815,7 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { seekChannel.setMessageHandler(nil) } - let closeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", - binaryMessenger: binaryMessenger, codec: codec) + let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) if let api = api { closeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -819,25 +833,21 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: FileHandle, completion: @escaping (Result) -> Void - ) { + func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( - pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index 7325b2692425..68ad038e8302 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -32,8 +32,10 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { return FileManager.default.isReadableFile(atPath: url) } - func fileExists(url: String) throws -> Bool { - return FileManager.default.fileExists(atPath: url) + func fileExists(url: String) throws -> FileExistsResult { + var isDirectory: ObjCBool = true + let exists = FileManager.default.fileExists(atPath: url, isDirectory: &isDirectory) + return FileExistsResult(exists: exists, isDirectory: isDirectory.boolValue) } func fileIsDirectory(url: String) throws -> Bool { diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index b5961b1cc9eb..56a954bf4b8e 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -9,8 +9,7 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' - show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -21,11 +20,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -34,6 +29,19 @@ List wrapResponse({ } return [error.code, error.message, error.details]; } +bool _deepEquals(Object? a, Object? b) { + if (a is List && b is List) { + return a.length == b.length && + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + } + if (a is Map && b is Map) { + return a.length == b.length && a.entries.every((MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key])); + } + return a == b; +} /// Provides overrides for the constructors and static members of each /// Dart proxy class. @@ -65,7 +73,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -135,10 +143,9 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> - _weakInstances = >{}; - final Map _strongInstances = - {}; + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -151,8 +158,7 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = - _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -160,12 +166,8 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers( - instanceManager: instanceManager, - ); - FileHandle.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -182,9 +184,8 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference( - instance, - ); + _weakInstances[identifier] = + WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -245,21 +246,15 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference( - int identifier, - ) { - final PigeonInternalProxyApiBaseClass? weakInstance = - _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = - _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance - .pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = - WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -281,10 +276,7 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance( - PigeonInternalProxyApiBaseClass instance, - int identifier, - ) { + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -313,7 +305,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -326,35 +318,28 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert( - arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', - ); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); try { - (instanceManager ?? PigeonInstanceManager.instance).remove( - arg_identifier!, - ); + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -369,9 +354,8 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -414,31 +398,77 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} + + +class FileExistsResult { + FileExistsResult({ + required this.exists, + required this.isDirectory, + }); + + bool exists; + + bool isDirectory; + + List _toList() { + return [ + exists, + isDirectory, + ]; + } + + Object encode() { + return _toList(); } + + static FileExistsResult decode(Object result) { + result as List; + return FileExistsResult( + exists: result[0]! as bool, + isDirectory: result[1]! as bool, + ); } @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference( - readValue(buffer)! as int, - ); - default: - return super.readValueOfType(type, buffer); + // ignore: avoid_equals_and_hash_code_on_mutable_classes + bool operator ==(Object other) { + if (other is! FileExistsResult || other.runtimeType != runtimeType) { + return false; + } + if (identical(this, other)) { + return true; } + return _deepEquals(encode(), other.encode()); } + + @override + // ignore: avoid_equals_and_hash_code_on_mutable_classes + int get hashCode => Object.hashAll(_toList()) +; } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -446,6 +476,9 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); + } else if (value is FileExistsResult) { + buffer.putUint8(129); + writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -454,6 +487,8 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { + case 129: + return FileExistsResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -464,13 +499,9 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({ - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty - ? '.$messageChannelSuffix' - : ''; + CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -478,16 +509,13 @@ class CrossFileDarwinApi { final String pigeonVar_messageChannelSuffix; Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -503,16 +531,13 @@ class CrossFileDarwinApi { } Future isReadableFile(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -532,17 +557,14 @@ class CrossFileDarwinApi { } } - Future fileExists(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; + Future fileExists(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -558,51 +580,18 @@ class CrossFileDarwinApi { message: 'Host platform returned null value for non-null return value.', ); } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future fileIsDirectory(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileIsDirectory$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; + return (pigeonVar_replyList[0] as FileExistsResult?)!; } } Future fileModificationDate(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -618,16 +607,13 @@ class CrossFileDarwinApi { } Future fileSize(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -643,16 +629,13 @@ class CrossFileDarwinApi { } Future> list(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -672,7 +655,6 @@ class CrossFileDarwinApi { } } } - class FileHandle extends PigeonInternalProxyApiBaseClass { /// Constructs [FileHandle] without creating the associated native object. /// @@ -695,46 +677,39 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + FileHandle.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -751,8 +726,7 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl'; @@ -761,9 +735,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -789,9 +762,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, count], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, count]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -817,9 +789,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -845,9 +816,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, offset], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, offset]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -873,9 +843,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -898,3 +867,4 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { ); } } + diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index fe6ec9bfd0a4..5ac93d84cf9e 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -51,12 +51,18 @@ base class DarwinScopedStorageXDirectory } @override - Future exists() => params.api.fileExists(params.uri); + Future exists() async { + final FileExistsResult result = await params.api.fileExists(params.uri); + return result.exists && result.isDirectory; + } @override Stream list(ListParams params) async* { for (final String url in await this.params.api.list(this.params.uri)) { - if (await this.params.api.fileIsDirectory(url)) { + final FileExistsResult existsResult = await this.params.api.fileExists( + this.params.uri, + ); + if (existsResult.isDirectory) { yield DarwinScopedStorageXDirectory( PlatformScopedStorageXDirectoryCreationParams(uri: url), ); diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 48b828e3a60a..5ca0e2b06236 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -63,7 +63,10 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { Future canRead() => params.api.isReadableFile(params.uri); @override - Future exists() => params.api.fileExists(params.uri); + Future exists() async { + final FileExistsResult result = await params.api.fileExists(params.uri); + return result.exists && !result.isDirectory; + } @override Future lastModified() async { @@ -87,7 +90,9 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { Stream openRead([int? start, int? end]) async* { final int? fileLength = await length(); if (fileLength == null) { - throw UnsupportedError('Cannot access file length.'); + throw UnsupportedError( + 'Cannot access file length of file with uri: ${params.uri}.', + ); } int bytesToRead = (end ?? fileLength) - (start ?? 0); @@ -95,7 +100,9 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); if (handle == null) { - throw UnsupportedError('Cannot access file length.'); + throw UnsupportedError( + 'Cannot create native `FileHandle` with uri: ${params.uri}.', + ); } try { @@ -127,7 +134,9 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { Future readAsBytes() async { final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); if (handle == null) { - throw UnsupportedError('Can not create file handle'); + throw UnsupportedError( + 'Cannot create native `FileHandle` with uri: ${params.uri}.', + ); } try { diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index c1a90aa3167e..6e507375bb5e 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -13,15 +13,19 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) +class FileExistsResult { + late bool exists; + + late bool isDirectory; +} + @HostApi() abstract class CrossFileDarwinApi { String? tryCreateBookmarkedUrl(String url); bool isReadableFile(String url); - bool fileExists(String url); - - bool fileIsDirectory(String url); + FileExistsResult fileExists(String url); int? fileModificationDate(String url); From 8b84b2350b75494da99507c1c51211b426777d08 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:49:12 -0500 Subject: [PATCH 101/398] formatting and docs --- .../Classes/CrossFileDarwinApis.g.swift | 244 +++++++++---- .../CrossFileDarwinApiImpl.swift | 4 +- .../FileHandleProxyAPIDelegate.swift | 4 +- .../lib/src/cross_file_darwin_apis.g.dart | 329 +++++++++++------- .../src/darwin_scoped_storage_cross_file.dart | 6 +- .../pigeons/cross_file_darwin_apis.dart | 24 +- 6 files changed, 413 insertions(+), 198 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift index d192813e5a1e..78dd2cd3cff9 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -59,7 +59,9 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -114,12 +116,12 @@ func deepEqualsCrossFileDarwinApis(_ lhs: Any?, _ rhs: Any?) -> Bool { func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { if let valueList = value as? [AnyHashable] { - for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } - return + for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } + return } if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { + for key in valueDict.keys { hasher.combine(key) deepHashCrossFileDarwinApis(value: valueDict[key]!, hasher: &hasher) } @@ -133,14 +135,12 @@ func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { return hasher.combine(String(describing: value)) } - /// Handles the callback when an object is deallocated. protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. func onDeinit(identifier: Int64) } - // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -156,14 +156,18 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, + delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( + identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = + objc_getAssociatedObject(instance, associatedObjectKey) + as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -175,7 +179,6 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } - /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -279,7 +282,8 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -360,7 +364,6 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } - private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -373,9 +376,15 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, + instanceManager: CrossFileDarwinApisPigeonInstanceManager? + ) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -390,7 +399,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -406,9 +417,13 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -428,7 +443,8 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiFileHandle } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -441,12 +457,15 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + private class InstanceManagerApiFinalizerDelegate: + CrossFileDarwinApisPigeonInternalFinalizerDelegate + { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -460,7 +479,9 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + init( + binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + ) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -469,18 +490,25 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiFileHandle.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: + FlutterStandardReaderWriter +{ unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: + CrossFileDarwinApisPigeonCodecReader + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -504,7 +532,9 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: + CrossFileDarwinApisPigeonCodecWriter + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -513,24 +543,26 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + { super.writeValue(value) return } - if let instance = value as? FileHandle { pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -548,20 +580,25 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( + data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( + data: data, pigeonRegistrar: pigeonRegistrar) } } +/// Result of a call to `CrossFileDarwinApi.fileExists`. +/// /// Generated class from Pigeon that represents data sent in messages. struct FileExistsResult: Hashable { + /// Whether the file exists. var exists: Bool + /// Whether th var isDirectory: Bool - // swift-format-ignore: AlwaysUseLowerCamelCase static func fromList(_ pigeonVar_list: [Any?]) -> FileExistsResult? { let exists = pigeonVar_list[0] as! Bool @@ -579,7 +616,8 @@ struct FileExistsResult: Hashable { ] } static func == (lhs: FileExistsResult, rhs: FileExistsResult) -> Bool { - return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) } + return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) + } func hash(into hasher: inout Hasher) { deepHashCrossFileDarwinApis(value: toList(), hasher: &hasher) } @@ -618,16 +656,25 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol CrossFileDarwinApi { + /// Attempt to create a bookmarked URL that serves as a persistent reference + /// to a file. func tryCreateBookmarkedUrl(url: String) throws -> String? + /// Whether the invoking object appears able to read a specified file. func isReadableFile(url: String) throws -> Bool + /// Whether a file or directory exists at a specified path. func fileExists(url: String) throws -> FileExistsResult + /// The file’s last modified date. func fileModificationDate(url: String) throws -> Int64? + /// The file’s size in bytes. func fileSize(url: String) throws -> Int64? + /// Performs a shallow search of the specified directory and returns the paths + /// of any contained items. func list(url: String) throws -> [String] } @@ -635,9 +682,17 @@ protocol CrossFileDarwinApi { class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + /// Attempt to create a bookmarked URL that serves as a persistent reference + /// to a file. + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -652,7 +707,11 @@ class CrossFileDarwinApiSetup { } else { tryCreateBookmarkedUrlChannel.setMessageHandler(nil) } - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + /// Whether the invoking object appears able to read a specified file. + let isReadableFileChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -667,7 +726,10 @@ class CrossFileDarwinApiSetup { } else { isReadableFileChannel.setMessageHandler(nil) } - let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + /// Whether a file or directory exists at a specified path. + let fileExistsChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileExistsChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -682,7 +744,11 @@ class CrossFileDarwinApiSetup { } else { fileExistsChannel.setMessageHandler(nil) } - let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + /// The file’s last modified date. + let fileModificationDateChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileModificationDateChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -697,7 +763,10 @@ class CrossFileDarwinApiSetup { } else { fileModificationDateChannel.setMessageHandler(nil) } - let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + /// The file’s size in bytes. + let fileSizeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileSizeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -712,7 +781,11 @@ class CrossFileDarwinApiSetup { } else { fileSizeChannel.setMessageHandler(nil) } - let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + /// Performs a shallow search of the specified directory and returns the paths + /// of any contained items. + let listChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { listChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -730,52 +803,73 @@ class CrossFileDarwinApiSetup { } } protocol PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle? - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? + /// Returns a file handle initialized for reading the file, device, or named + /// socket at the specified path. + func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? + /// Reads data synchronously up to the specified number of bytes. + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) + throws -> FlutterStandardTypedData? + /// Reads the available data synchronously up to the end of file or maximum + /// number of bytes. + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws + -> FlutterStandardTypedData? + /// Moves the file pointer to the specified offset within the file. func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws + /// Disallows further access to the represented file or communications channel + /// and signals end of file on communications channels that permit writing. func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws } protocol PigeonApiProtocolFileHandle { } -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateFileHandle - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { + init( + pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateFileHandle + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let forReadingFromUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl", binaryMessenger: binaryMessenger, codec: codec) + let forReadingAtPathChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { - forReadingFromUrlChannel.setMessageHandler { message, reply in + forReadingAtPathChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let urlArg = args[0] as! String + let pathArg = args[0] as! String do { - let result = try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg) + let result = try api.pigeonDelegate.forReadingAtPath(pigeonApi: api, path: pathArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) } } } else { - forReadingFromUrlChannel.setMessageHandler(nil) + forReadingAtPathChannel.setMessageHandler(nil) } - let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) + let readUpToCountChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readUpToCountChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let countArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + let result = try api.pigeonDelegate.readUpToCount( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -784,13 +878,16 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { readUpToCountChannel.setMessageHandler(nil) } - let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) + let readToEndChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readToEndChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.readToEnd( + pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -799,14 +896,17 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { readToEndChannel.setMessageHandler(nil) } - let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) + let seekChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { seekChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let offsetArg = args[1] as! Int64 do { - try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) + try api.pigeonDelegate.seek( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -815,7 +915,9 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { seekChannel.setMessageHandler(nil) } - let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) + let closeChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { closeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -833,21 +935,25 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: FileHandle, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index 68ad038e8302..eb1f968ba4fa 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -10,7 +10,7 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { let nativeUrl = URL(fileURLWithPath: url) if nativeUrl.startAccessingSecurityScopedResource() { defer { nativeUrl.stopAccessingSecurityScopedResource() } - + let data = try nativeUrl.bookmarkData( options: [], includingResourceValuesForKeys: nil, @@ -20,7 +20,7 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { var isStale: Bool = true let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - if (!isStale) { + if !isStale { return bookmarkedUrl.path } } diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift index 9f2b02bb0d73..05b73be383ff 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift @@ -10,8 +10,8 @@ import Foundation /// This class may handle instantiating native object instances that are attached to a Dart instance /// or handle method calls on the associated native class or an instance of that class. class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: String) throws -> FileHandle? { - return FileHandle(forReadingAtPath: url) + func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? { + return FileHandle(forReadingAtPath: path) } func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 56a954bf4b8e..d682c5bf6ae2 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' + show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -20,7 +21,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -29,16 +34,21 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed - .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + a.indexed.every( + ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), + ); } if (a is Map && b is Map) { - return a.length == b.length && a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + return a.length == b.length && + a.entries.every( + (MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key]), + ); } return a == b; } @@ -52,12 +62,12 @@ bool _deepEquals(Object? a, Object? b) { /// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. @visibleForTesting class PigeonOverrides { - /// Overrides [FileHandle.forReadingFromUrl]. - static Future Function(String)? fileHandle_forReadingFromUrl; + /// Overrides [FileHandle.forReadingAtPath]. + static Future Function(String)? fileHandle_forReadingAtPath; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { - fileHandle_forReadingFromUrl = null; + fileHandle_forReadingAtPath = null; } } @@ -73,7 +83,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -143,9 +153,10 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; + final Map> + _weakInstances = >{}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -158,7 +169,8 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = + _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -166,8 +178,12 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager, + ); + FileHandle.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -184,8 +200,9 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference( + instance, + ); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -246,15 +263,21 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference( + int identifier, + ) { + final PigeonInternalProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance + .pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = + WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -276,7 +299,10 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + void addHostCreatedInstance( + PigeonInternalProxyApiBaseClass instance, + int identifier, + ) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -305,7 +331,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -318,28 +344,35 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.', + ); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + assert( + arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', + ); try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); + (instanceManager ?? PigeonInstanceManager.instance).remove( + arg_identifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -354,8 +387,9 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -398,49 +432,48 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference( + readValue(buffer)! as int, + ); + default: + return super.readValueOfType(type, buffer); + } + } +} +/// Result of a call to `CrossFileDarwinApi.fileExists`. class FileExistsResult { - FileExistsResult({ - required this.exists, - required this.isDirectory, - }); + FileExistsResult({required this.exists, required this.isDirectory}); + /// Whether the file exists. bool exists; + /// Whether th bool isDirectory; List _toList() { - return [ - exists, - isDirectory, - ]; + return [exists, isDirectory]; } Object encode() { - return _toList(); } + return _toList(); + } static FileExistsResult decode(Object result) { result as List; @@ -464,11 +497,9 @@ class FileExistsResult { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()) -; + int get hashCode => Object.hashAll(_toList()); } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -476,7 +507,7 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileExistsResult) { + } else if (value is FileExistsResult) { buffer.putUint8(129); writeValue(buffer, value.encode()); } else { @@ -487,7 +518,7 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: return FileExistsResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -499,23 +530,32 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + CrossFileDarwinApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); final String pigeonVar_messageChannelSuffix; + /// Attempt to create a bookmarked URL that serves as a persistent reference + /// to a file. Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -530,14 +570,18 @@ class CrossFileDarwinApi { } } + /// Whether the invoking object appears able to read a specified file. Future isReadableFile(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -557,14 +601,18 @@ class CrossFileDarwinApi { } } + /// Whether a file or directory exists at a specified path. Future fileExists(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -584,14 +632,18 @@ class CrossFileDarwinApi { } } + /// The file’s last modified date. Future fileModificationDate(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -606,14 +658,18 @@ class CrossFileDarwinApi { } } + /// The file’s size in bytes. Future fileSize(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -628,14 +684,19 @@ class CrossFileDarwinApi { } } + /// Performs a shallow search of the specified directory and returns the paths + /// of any contained items. Future> list(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -655,6 +716,10 @@ class CrossFileDarwinApi { } } } + +/// An object-oriented wrapper for a file descriptor. +/// +/// See https://developer.apple.com/documentation/foundation/filehandle. class FileHandle extends PigeonInternalProxyApiBaseClass { /// Constructs [FileHandle] without creating the associated native object. /// @@ -677,66 +742,77 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + FileHandle.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } } } - static Future forReadingFromUrl( - String url, { + /// Returns a file handle initialized for reading the file, device, or named + /// socket at the specified path. + static Future forReadingAtPath( + String path, { BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) async { - if (PigeonOverrides.fileHandle_forReadingFromUrl != null) { - return PigeonOverrides.fileHandle_forReadingFromUrl!(url); + if (PigeonOverrides.fileHandle_forReadingAtPath != null) { + return PigeonOverrides.fileHandle_forReadingAtPath!(path); } final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingFromUrl'; + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [path], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -751,6 +827,7 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } + /// Reads data synchronously up to the specified number of bytes. Future readUpToCount(int count) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; @@ -762,8 +839,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, count]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, count], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -778,6 +856,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } + /// Reads the available data synchronously up to the end of file or maximum + /// number of bytes. Future readToEnd() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; @@ -789,8 +869,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -805,6 +886,7 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } + /// Moves the file pointer to the specified offset within the file. Future seek(int offset) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; @@ -816,8 +898,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, offset]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, offset], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -832,6 +915,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } } + /// Disallows further access to the represented file or communications channel + /// and signals end of file on communications channels that permit writing. Future close() async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecFileHandle; @@ -843,8 +928,9 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -867,4 +953,3 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { ); } } - diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 5ca0e2b06236..b8fe0a689ca6 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -47,6 +47,8 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { /// Attempt to create a bookmarked file that serves as a persistent reference /// to the file. + /// + /// Returns null if the file could not be bookmarked. Future toBookmarkedFile() async { final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( params.uri, @@ -98,7 +100,7 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { int bytesToRead = (end ?? fileLength) - (start ?? 0); assert(bytesToRead >= 0); - final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); + final FileHandle? handle = await FileHandle.forReadingAtPath(params.uri); if (handle == null) { throw UnsupportedError( 'Cannot create native `FileHandle` with uri: ${params.uri}.', @@ -132,7 +134,7 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { @override Future readAsBytes() async { - final FileHandle? handle = await FileHandle.forReadingFromUrl(params.uri); + final FileHandle? handle = await FileHandle.forReadingAtPath(params.uri); if (handle == null) { throw UnsupportedError( 'Cannot create native `FileHandle` with uri: ${params.uri}.', diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index 6e507375bb5e..0172d1a60b08 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -13,37 +13,59 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) +/// Result of a call to `CrossFileDarwinApi.fileExists`. class FileExistsResult { + /// Whether the file exists. late bool exists; + /// Whether th late bool isDirectory; } @HostApi() abstract class CrossFileDarwinApi { + /// Attempt to create a bookmarked URL that serves as a persistent reference + /// to a file. String? tryCreateBookmarkedUrl(String url); + /// Whether the invoking object appears able to read a specified file. bool isReadableFile(String url); + /// Whether a file or directory exists at a specified path. FileExistsResult fileExists(String url); + /// The file’s last modified date. int? fileModificationDate(String url); + /// The file’s size in bytes. int? fileSize(String url); + /// Performs a shallow search of the specified directory and returns the paths + /// of any contained items. List list(String url); } +/// An object-oriented wrapper for a file descriptor. +/// +/// See https://developer.apple.com/documentation/foundation/filehandle. @ProxyApi() abstract class FileHandle { + /// Returns a file handle initialized for reading the file, device, or named + /// socket at the specified path. @static - FileHandle? forReadingFromUrl(String url); + FileHandle? forReadingAtPath(String path); + /// Reads data synchronously up to the specified number of bytes. Uint8List? readUpToCount(int count); + /// Reads the available data synchronously up to the end of file or maximum + /// number of bytes. Uint8List? readToEnd(); + /// Moves the file pointer to the specified offset within the file. void seek(int offset); + /// Disallows further access to the represented file or communications channel + /// and signals end of file on communications channels that permit writing. void close(); } From 14acd6eeca507f9cea51ed9991569a056014f095 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 12:54:10 -0500 Subject: [PATCH 102/398] make tests --- .../CrossFileDarwinApiImpl.swift | 19 +++++++++++++------ .../pigeons/cross_file_darwin_apis.dart | 1 + 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index eb1f968ba4fa..454df655ac2a 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -5,7 +5,14 @@ import Flutter import Foundation +/// Implementation of `CrossFileDarwinApi`. class CrossFileDarwinApiImpl: CrossFileDarwinApi { + let fileManager: FileManager + + init(fileManager: FileManager = FileManager.default) { + self.fileManager = fileManager + } + func tryCreateBookmarkedUrl(url: String) throws -> String? { let nativeUrl = URL(fileURLWithPath: url) if nativeUrl.startAccessingSecurityScopedResource() { @@ -29,24 +36,24 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { } func isReadableFile(url: String) throws -> Bool { - return FileManager.default.isReadableFile(atPath: url) + return fileManager.isReadableFile(atPath: url) } func fileExists(url: String) throws -> FileExistsResult { var isDirectory: ObjCBool = true - let exists = FileManager.default.fileExists(atPath: url, isDirectory: &isDirectory) + let exists = fileManager.fileExists(atPath: url, isDirectory: &isDirectory) return FileExistsResult(exists: exists, isDirectory: isDirectory.boolValue) } func fileIsDirectory(url: String) throws -> Bool { var isDirectory: ObjCBool = true - return FileManager.default.fileExists(atPath: url, isDirectory: &isDirectory) + return fileManager.fileExists(atPath: url, isDirectory: &isDirectory) && isDirectory.boolValue } func fileModificationDate(url: String) throws -> Int64? { let attributes: NSDictionary = - try FileManager.default.attributesOfItem(atPath: url) as NSDictionary + try fileManager.attributesOfItem(atPath: url) as NSDictionary if let date = attributes.fileModificationDate() { return Int64(date.timeIntervalSince1970 * 1000) } @@ -56,11 +63,11 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { func fileSize(url: String) throws -> Int64? { let attributes: NSDictionary = - try FileManager.default.attributesOfItem(atPath: url) as NSDictionary + try fileManager.attributesOfItem(atPath: url) as NSDictionary return Int64(attributes.fileSize()) } func list(url: String) throws -> [String] { - return try FileManager.default.contentsOfDirectory(atPath: url) + return try fileManager.contentsOfDirectory(atPath: url) } } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index 0172d1a60b08..97d0a9107281 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -22,6 +22,7 @@ class FileExistsResult { late bool isDirectory; } +/// Api for getting access to file information. @HostApi() abstract class CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference From 82d48339c096f7eac3e901e640a9568bf5c3068f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:03:52 -0500 Subject: [PATCH 103/398] add extensions --- ...darwin_scoped_storage_cross_directory.dart | 20 +++++++++++++++---- .../src/darwin_scoped_storage_cross_file.dart | 19 +++++++++++++----- ...atform_scoped_storage_cross_directory.dart | 2 +- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 5ac93d84cf9e..ece6cacbbd90 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -25,8 +25,8 @@ base class DarwinScopedStorageXDirectoryCreationParams } /// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. -base class DarwinScopedStorageXDirectory - extends PlatformScopedStorageXDirectory { +base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory + with DarwinScopedStorageXDirectoryExtension { /// Constructs an [DarwinScopedStorageXDirectory]. DarwinScopedStorageXDirectory(super.params) : super.implementation(); @@ -36,8 +36,10 @@ base class DarwinScopedStorageXDirectory ? super.params as DarwinScopedStorageXDirectoryCreationParams : DarwinScopedStorageXDirectoryCreationParams(uri: super.params.uri); - /// Attempt to create a bookmarked directory that serves as a persistent - /// reference to the directory. + @override + PlatformXFileEntityExtension? get extension => this; + + @override Future toBookmarkedDirectory() async { final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( params.uri, @@ -74,3 +76,13 @@ base class DarwinScopedStorageXDirectory } } } + +/// Provides platform specific features for [DarwinScopedStorageXDirectory]. +mixin DarwinScopedStorageXDirectoryExtension + implements PlatformScopedStorageXDirectoryExtension { + /// Attempt to create a bookmarked directory that serves as a persistent + /// reference to the directory. + /// + /// Returns null if the directory could not be bookmarked. + Future toBookmarkedDirectory(); +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index b8fe0a689ca6..2201ce568870 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -28,7 +28,7 @@ base class DarwinScopedStorageXFileCreationParams } /// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. -base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { +base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile with DarwinScopedStorageXFileExtension { /// Constructs a [DarwinScopedStorageXFile]. DarwinScopedStorageXFile(super.params) : super.implementation(); @@ -45,10 +45,10 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { ? super.params as DarwinScopedStorageXFileCreationParams : DarwinScopedStorageXFileCreationParams(uri: super.params.uri); - /// Attempt to create a bookmarked file that serves as a persistent reference - /// to the file. - /// - /// Returns null if the file could not be bookmarked. + @override + PlatformXFileEntityExtension? get extension => this; + + @override Future toBookmarkedFile() async { final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( params.uri, @@ -158,3 +158,12 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { return encoding.decodeStream(openRead()); } } + +/// Provides platform specific features for [DarwinScopedStorageXFile]. +mixin DarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension { + /// Attempt to create a bookmarked file that serves as a persistent reference + /// to the file. + /// + /// Returns null if the file could not be bookmarked. + Future toBookmarkedFile(); +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index 0156289e5bea..df2cbfe4520f 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -65,7 +65,7 @@ base class PlatformScopedStorageXDirectoryCreationParams /// Future platformMethod(); /// } /// ``` -mixin ScopedStoragePlatformXDirectoryExtension +mixin PlatformScopedStorageXDirectoryExtension implements PlatformXDirectoryExtension {} /// A reference to a directory (or folder) on the file system within a devices From dd280a2bc2ab2a83817b94f2a930819f50831e30 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:17:10 -0500 Subject: [PATCH 104/398] export extensions and add exception docs --- .../cross_file/cross_file_darwin/lib/cross_file_darwin.dart | 5 +++++ .../lib/src/darwin_scoped_storage_cross_directory.dart | 3 ++- .../lib/src/darwin_scoped_storage_cross_file.dart | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 70d1d8383760..f3c6d80e9f10 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -6,3 +6,8 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXFileEntity; export 'src/cross_file_darwin.dart'; + +export 'src/darwin_scoped_storage_cross_directory.dart' + show DarwinScopedStorageXDirectoryExtension; +export 'src/darwin_scoped_storage_cross_file.dart' + show DarwinScopedStorageXFileExtension; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index ece6cacbbd90..69554bfda20a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -83,6 +83,7 @@ mixin DarwinScopedStorageXDirectoryExtension /// Attempt to create a bookmarked directory that serves as a persistent /// reference to the directory. /// - /// Returns null if the directory could not be bookmarked. + /// Throws exception if the directory could not be bookmarked or null if the + /// bookmark is stale. Future toBookmarkedDirectory(); } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 2201ce568870..506dae98a60e 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -164,6 +164,7 @@ mixin DarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExt /// Attempt to create a bookmarked file that serves as a persistent reference /// to the file. /// - /// Returns null if the file could not be bookmarked. + /// Throws exception if the file could not be bookmarked or null if the + /// bookmark is stale. Future toBookmarkedFile(); } From 0373d5edd2ecf56685bfbae4b449e7bf7f1dcfef Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:34:22 -0500 Subject: [PATCH 105/398] half of file tests --- .../plugin_integration_test.dart | 22 +- .../pigeons/cross_file_darwin_apis.dart | 2 +- ...darwin_scoped_storage_cross_file_test.dart | 257 ++++++++++++++++++ ..._scoped_storage_cross_file_test.mocks.dart | 182 +++++++++++++ 4 files changed, 446 insertions(+), 17 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart index 7d792c675453..621977be68c7 100644 --- a/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart +++ b/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart @@ -1,24 +1,14 @@ -// This is a basic Flutter integration test. -// -// Since integration tests run in a full Flutter application, they can interact -// with the host side of a plugin implementation, unlike Dart unit tests. -// -// For more information about Flutter integration tests, please see -// https://flutter.dev/to/integration-testing +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:cross_file_darwin/cross_file_darwin.dart'; - void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('getPlatformVersion test', (WidgetTester tester) async { - final CrossFileDarwin plugin = CrossFileDarwin(); - final String? version = await plugin.getPlatformVersion(); - // The version string depends on the host platform running the test, so - // just assert that some non-empty string is returned. - expect(version?.isNotEmpty, true); - }); + // Since this test is lacking integration tests, this test ensures the example + // app can be launched on an emulator/device. + testWidgets('Launch Test', (WidgetTester tester) async {}); } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index 97d0a9107281..2ee362f1f47d 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -35,7 +35,7 @@ abstract class CrossFileDarwinApi { /// Whether a file or directory exists at a specified path. FileExistsResult fileExists(String url); - /// The file’s last modified date. + /// The file’s last modified date in milliseconds since epoch. int? fileModificationDate(String url); /// The file’s size in bytes. diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart new file mode 100644 index 000000000000..d17f5b62e5ba --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -0,0 +1,257 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; +import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'darwin_scoped_storage_cross_file_test.mocks.dart'; + +@GenerateMocks([FileHandle, CrossFileDarwinApi]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + PigeonOverrides.pigeon_reset(); + }); + + test('lastModified', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const modificationDate = 123; + when( + mockApi.fileModificationDate(uri), + ).thenAnswer((_) async => modificationDate); + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect( + await file.lastModified(), + DateTime.fromMillisecondsSinceEpoch(modificationDate), + ); + }); + + test('length', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const size = 123; + when(mockApi.fileSize(uri)).thenAnswer((_) async => size); + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.length(), size); + }); + + group('openRead', () { + test('openRead finishes successfully', () async { + final testBytes = Uint8List.fromList([0, 1, 2]); + + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); + + final mockFileHandle = MockFileHandle(); + setUpFileHandleWithBytes(mockFileHandle, testBytes); + PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { + expect(path, uri); + return mockFileHandle; + }; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(combineLists(await file.openRead().toList()), testBytes); + }); + + test( + 'openRead finishes successfully with file larger than max array len', + () async { + final testBytes = Uint8List.fromList( + List.filled(DarwinScopedStorageXFile.maxByteArrayLen + 1, 0), + ); + + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); + + final mockFileHandle = MockFileHandle(); + setUpFileHandleWithBytes(mockFileHandle, testBytes); + PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { + expect(path, uri); + return mockFileHandle; + }; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(combineLists(await file.openRead().toList()), testBytes); + }, + ); + + test('openRead finishes successfully with subset of array', () async { + final testBytes = Uint8List.fromList([0, 0, 0, 1, 1, 1, 0, 0, 0]); + + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); + + final mockFileHandle = MockFileHandle(); + setUpFileHandleWithBytes(mockFileHandle, testBytes); + PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { + expect(path, uri); + return mockFileHandle; + }; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(combineLists(await file.openRead(3, 6).toList()), [1, 1, 1]); + }); + }); + + test('readAsBytes', () async { + final testBytes = Uint8List.fromList([0, 1, 2]); + + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); + + final mockFileHandle = MockFileHandle(); + when(mockFileHandle.readToEnd()).thenAnswer((_) async => testBytes); + PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { + expect(path, uri); + return mockFileHandle; + }; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.readAsBytes(), testBytes); + }); + // + // test('readAsString', () async { + // const testString = 'Hello, World!'; + // final Uint8List testBytes = utf8.encode(testString); + // + // final mockApi = MockCrossFileDarwinApi(); + // const uri = 'uri'; + // when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); + // + // const uri = 'uri'; + // android.PigeonOverrides.documentFile_fromSingleUri = + // ({required String singleUri}) { + // expect(singleUri, uri); + // return mockDocumentFile; + // }; + // + // final mockInputStream = MockInputStream(); + // setUpInputStreamWithBytes(mockInputStream, testBytes); + // + // final mockContentResolver = MockContentResolver(); + // when( + // mockContentResolver.openInputStream(uri), + // ).thenAnswer((_) async => mockInputStream); + // android.PigeonOverrides.contentResolver_instance = mockContentResolver; + // + // final file = AndroidScopedStorageXFile( + // const PlatformScopedStorageXFileCreationParams(uri: uri), + // ); + // + // expect(await file.readAsString(), testString); + // }); + // + // test('canRead', () async { + // final mockApi = MockCrossFileDarwinApi(); + // const canRead = false; + // when(mockDocumentFile.canRead()).thenAnswer((_) async => canRead); + // + // const uri = 'uri'; + // android.PigeonOverrides.documentFile_fromSingleUri = + // ({required String singleUri}) { + // expect(singleUri, uri); + // return mockDocumentFile; + // }; + // + // final file = AndroidScopedStorageXFile( + // const PlatformScopedStorageXFileCreationParams(uri: uri), + // ); + // + // expect(await file.canRead(), canRead); + // }); + // + // test('exists', () async { + // final mockApi = MockCrossFileDarwinApi(); + // when(mockDocumentFile.exists()).thenAnswer((_) async => true); + // when(mockDocumentFile.isFile()).thenAnswer((_) async => true); + // + // const uri = 'uri'; + // android.PigeonOverrides.documentFile_fromSingleUri = + // ({required String singleUri}) { + // expect(singleUri, uri); + // return mockDocumentFile; + // }; + // + // final file = AndroidScopedStorageXFile( + // const PlatformScopedStorageXFileCreationParams(uri: uri), + // ); + // + // expect(await file.exists(), true); + // }); + // + // test('name', () async { + // final mockApi = MockCrossFileDarwinApi(); + // const name = 'name'; + // when(mockDocumentFile.getName()).thenAnswer((_) async => name); + // + // const uri = 'uri'; + // android.PigeonOverrides.documentFile_fromSingleUri = + // ({required String singleUri}) { + // expect(singleUri, uri); + // return mockDocumentFile; + // }; + // + // final file = AndroidScopedStorageXFile( + // const PlatformScopedStorageXFileCreationParams(uri: uri), + // ); + // + // expect(await file.name(), name); + // }); +} + +void setUpFileHandleWithBytes(MockFileHandle mockFileHandle, Uint8List bytes) { + int offset = 0; + + when(mockFileHandle.seek(any)).thenAnswer((Invocation invocation) async { + offset = invocation.positionalArguments[0] as int; + }); + + when(mockFileHandle.readUpToCount(any)).thenAnswer(( + Invocation invocation, + ) async { + final count = invocation.positionalArguments[0] as int; + final Uint8List nextBytes = bytes.sublist(offset, offset + count); + offset += count; + return nextBytes; + }); +} + +Uint8List combineLists(List lists) { + return Uint8List.fromList( + lists.expand((Uint8List element) => element).toList(), + ); +} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart new file mode 100644 index 000000000000..2d67e03be146 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart @@ -0,0 +1,182 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; +import 'dart:typed_data' as _i4; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i5; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeFileHandle_1 extends _i1.SmartFake implements _i2.FileHandle { + _FakeFileHandle_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeFileExistsResult_2 extends _i1.SmartFake + implements _i2.FileExistsResult { + _FakeFileExistsResult_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [FileHandle]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockFileHandle extends _i1.Mock implements _i2.FileHandle { + MockFileHandle() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future<_i4.Uint8List?> readUpToCount(int? count) => + (super.noSuchMethod( + Invocation.method(#readUpToCount, [count]), + returnValue: _i3.Future<_i4.Uint8List?>.value(), + ) + as _i3.Future<_i4.Uint8List?>); + + @override + _i3.Future<_i4.Uint8List?> readToEnd() => + (super.noSuchMethod( + Invocation.method(#readToEnd, []), + returnValue: _i3.Future<_i4.Uint8List?>.value(), + ) + as _i3.Future<_i4.Uint8List?>); + + @override + _i3.Future seek(int? offset) => + (super.noSuchMethod( + Invocation.method(#seek, [offset]), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i3.Future close() => + (super.noSuchMethod( + Invocation.method(#close, []), + returnValue: _i3.Future.value(), + returnValueForMissingStub: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i2.FileHandle pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeFileHandle_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.FileHandle); +} + +/// A class which mocks [CrossFileDarwinApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCrossFileDarwinApi extends _i1.Mock + implements _i2.CrossFileDarwinApi { + MockCrossFileDarwinApi() { + _i1.throwOnMissingStub(this); + } + + @override + String get pigeonVar_messageChannelSuffix => + (super.noSuchMethod( + Invocation.getter(#pigeonVar_messageChannelSuffix), + returnValue: _i5.dummyValue( + this, + Invocation.getter(#pigeonVar_messageChannelSuffix), + ), + ) + as String); + + @override + _i3.Future tryCreateBookmarkedUrl(String? url) => + (super.noSuchMethod( + Invocation.method(#tryCreateBookmarkedUrl, [url]), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i3.Future isReadableFile(String? url) => + (super.noSuchMethod( + Invocation.method(#isReadableFile, [url]), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future<_i2.FileExistsResult> fileExists(String? url) => + (super.noSuchMethod( + Invocation.method(#fileExists, [url]), + returnValue: _i3.Future<_i2.FileExistsResult>.value( + _FakeFileExistsResult_2( + this, + Invocation.method(#fileExists, [url]), + ), + ), + ) + as _i3.Future<_i2.FileExistsResult>); + + @override + _i3.Future fileModificationDate(String? url) => + (super.noSuchMethod( + Invocation.method(#fileModificationDate, [url]), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i3.Future fileSize(String? url) => + (super.noSuchMethod( + Invocation.method(#fileSize, [url]), + returnValue: _i3.Future.value(), + ) + as _i3.Future); + + @override + _i3.Future> list(String? url) => + (super.noSuchMethod( + Invocation.method(#list, [url]), + returnValue: _i3.Future>.value([]), + ) + as _i3.Future>); +} From 38eb1d93be0cf189a930d4a56b6ae651088fca3a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 17:44:45 -0500 Subject: [PATCH 106/398] dart unit tests for file --- .../src/darwin_scoped_storage_cross_file.dart | 11 +- .../cross_file/cross_file_darwin/pubspec.yaml | 1 + ...darwin_scoped_storage_cross_file_test.dart | 150 +++++++----------- 3 files changed, 68 insertions(+), 94 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 506dae98a60e..52ae9852b81a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -8,6 +8,7 @@ import 'dart:math'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; +import 'package:path/path.dart' as path; import 'cross_file_darwin_apis.g.dart'; @@ -28,7 +29,8 @@ base class DarwinScopedStorageXFileCreationParams } /// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. -base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile with DarwinScopedStorageXFileExtension { +base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile + with DarwinScopedStorageXFileExtension { /// Constructs a [DarwinScopedStorageXFile]. DarwinScopedStorageXFile(super.params) : super.implementation(); @@ -84,9 +86,7 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile with Darw Future length() => params.api.fileSize(params.uri); @override - Future name() { - throw UnimplementedError(); - } + Future name() async => path.basename(params.uri); @override Stream openRead([int? start, int? end]) async* { @@ -160,7 +160,8 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile with Darw } /// Provides platform specific features for [DarwinScopedStorageXFile]. -mixin DarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension { +mixin DarwinScopedStorageXFileExtension + implements PlatformScopedStorageXFileExtension { /// Attempt to create a bookmarked file that serves as a persistent reference /// to the file. /// diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 7c056da42136..f6af898738d6 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -28,6 +28,7 @@ dependencies: path: ../cross_file_platform_interface flutter: sdk: flutter + path: ^1.9.1 dev_dependencies: build_runner: ^2.10.4 diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index d17f5b62e5ba..0bda183f4440 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -7,7 +7,6 @@ import 'dart:typed_data'; import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; @@ -143,94 +142,67 @@ void main() { expect(await file.readAsBytes(), testBytes); }); - // - // test('readAsString', () async { - // const testString = 'Hello, World!'; - // final Uint8List testBytes = utf8.encode(testString); - // - // final mockApi = MockCrossFileDarwinApi(); - // const uri = 'uri'; - // when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); - // - // const uri = 'uri'; - // android.PigeonOverrides.documentFile_fromSingleUri = - // ({required String singleUri}) { - // expect(singleUri, uri); - // return mockDocumentFile; - // }; - // - // final mockInputStream = MockInputStream(); - // setUpInputStreamWithBytes(mockInputStream, testBytes); - // - // final mockContentResolver = MockContentResolver(); - // when( - // mockContentResolver.openInputStream(uri), - // ).thenAnswer((_) async => mockInputStream); - // android.PigeonOverrides.contentResolver_instance = mockContentResolver; - // - // final file = AndroidScopedStorageXFile( - // const PlatformScopedStorageXFileCreationParams(uri: uri), - // ); - // - // expect(await file.readAsString(), testString); - // }); - // - // test('canRead', () async { - // final mockApi = MockCrossFileDarwinApi(); - // const canRead = false; - // when(mockDocumentFile.canRead()).thenAnswer((_) async => canRead); - // - // const uri = 'uri'; - // android.PigeonOverrides.documentFile_fromSingleUri = - // ({required String singleUri}) { - // expect(singleUri, uri); - // return mockDocumentFile; - // }; - // - // final file = AndroidScopedStorageXFile( - // const PlatformScopedStorageXFileCreationParams(uri: uri), - // ); - // - // expect(await file.canRead(), canRead); - // }); - // - // test('exists', () async { - // final mockApi = MockCrossFileDarwinApi(); - // when(mockDocumentFile.exists()).thenAnswer((_) async => true); - // when(mockDocumentFile.isFile()).thenAnswer((_) async => true); - // - // const uri = 'uri'; - // android.PigeonOverrides.documentFile_fromSingleUri = - // ({required String singleUri}) { - // expect(singleUri, uri); - // return mockDocumentFile; - // }; - // - // final file = AndroidScopedStorageXFile( - // const PlatformScopedStorageXFileCreationParams(uri: uri), - // ); - // - // expect(await file.exists(), true); - // }); - // - // test('name', () async { - // final mockApi = MockCrossFileDarwinApi(); - // const name = 'name'; - // when(mockDocumentFile.getName()).thenAnswer((_) async => name); - // - // const uri = 'uri'; - // android.PigeonOverrides.documentFile_fromSingleUri = - // ({required String singleUri}) { - // expect(singleUri, uri); - // return mockDocumentFile; - // }; - // - // final file = AndroidScopedStorageXFile( - // const PlatformScopedStorageXFileCreationParams(uri: uri), - // ); - // - // expect(await file.name(), name); - // }); + + test('readAsString', () async { + const testString = 'Hello, World!'; + final Uint8List testBytes = utf8.encode(testString); + + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); + + final mockFileHandle = MockFileHandle(); + setUpFileHandleWithBytes(mockFileHandle, testBytes); + PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { + expect(path, uri); + return mockFileHandle; + }; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.readAsString(), testString); + }); + + test('canRead', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const canRead = false; + when(mockApi.isReadableFile(uri)).thenAnswer((_) async => canRead); + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.canRead(), canRead); + }); + + test('exists', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileExists(uri)).thenAnswer( + (_) async => FileExistsResult(exists: true, isDirectory: false), + ); + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.exists(), true); + }); + + test('name', () async { + final mockApi = MockCrossFileDarwinApi(); + const name = 'myfile.txt'; + const uri = 'hello/$name'; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.name(), name); + }); } void setUpFileHandleWithBytes(MockFileHandle mockFileHandle, Uint8List bytes) { From 51a74e21194f3cff382ca9e223c9aa72c55129d8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 21 Jan 2026 18:50:24 -0500 Subject: [PATCH 107/398] directory tests --- ...d_scoped_storage_cross_directory_test.dart | 2 +- ...darwin_scoped_storage_cross_directory.dart | 2 +- ...n_scoped_storage_cross_directory_test.dart | 56 ++++++++++ ...ed_storage_cross_directory_test.mocks.dart | 105 ++++++++++++++++++ 4 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart index cfb389489db2..9d8059f5de82 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart @@ -70,6 +70,6 @@ void main() { .map((PlatformXFileEntity entity) => entity.params.uri) .toList(); - expect(entityUris, ['fileUri']); + expect(entityUris, [fileUri]); }); } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 69554bfda20a..e8674a0c32af 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -62,7 +62,7 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory Stream list(ListParams params) async* { for (final String url in await this.params.api.list(this.params.uri)) { final FileExistsResult existsResult = await this.params.api.fileExists( - this.params.uri, + url, ); if (existsResult.isDirectory) { yield DarwinScopedStorageXDirectory( diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart new file mode 100644 index 000000000000..542e0a5a87ba --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -0,0 +1,56 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; +import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_directory.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'darwin_scoped_storage_cross_directory_test.mocks.dart'; + +@GenerateMocks([CrossFileDarwinApi]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + PigeonOverrides.pigeon_reset(); + }); + + test('exists', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + when(mockApi.fileExists(uri)).thenAnswer( + (_) async => FileExistsResult(exists: true, isDirectory: true), + ); + + final file = DarwinScopedStorageXDirectory( + DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.exists(), true); + }); + + test('list', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const fileUri = 'fileUri'; + when(mockApi.list(any)).thenAnswer((_) async => [fileUri]); + when(mockApi.fileExists(fileUri)).thenAnswer( + (_) async => FileExistsResult(exists: true, isDirectory: false), + ); + + final dir = DarwinScopedStorageXDirectory( + DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), + ); + + final List entityUris = await dir + .list(ListParams()) + .map((PlatformXFileEntity entity) => entity.params.uri) + .toList(); + + expect(entityUris, [fileUri]); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart new file mode 100644 index 000000000000..23a7b78e74ad --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart @@ -0,0 +1,105 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i4; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i3; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakeFileExistsResult_0 extends _i1.SmartFake + implements _i2.FileExistsResult { + _FakeFileExistsResult_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [CrossFileDarwinApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCrossFileDarwinApi extends _i1.Mock + implements _i2.CrossFileDarwinApi { + MockCrossFileDarwinApi() { + _i1.throwOnMissingStub(this); + } + + @override + String get pigeonVar_messageChannelSuffix => + (super.noSuchMethod( + Invocation.getter(#pigeonVar_messageChannelSuffix), + returnValue: _i3.dummyValue( + this, + Invocation.getter(#pigeonVar_messageChannelSuffix), + ), + ) + as String); + + @override + _i4.Future tryCreateBookmarkedUrl(String? url) => + (super.noSuchMethod( + Invocation.method(#tryCreateBookmarkedUrl, [url]), + returnValue: _i4.Future.value(), + ) + as _i4.Future); + + @override + _i4.Future isReadableFile(String? url) => + (super.noSuchMethod( + Invocation.method(#isReadableFile, [url]), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); + + @override + _i4.Future<_i2.FileExistsResult> fileExists(String? url) => + (super.noSuchMethod( + Invocation.method(#fileExists, [url]), + returnValue: _i4.Future<_i2.FileExistsResult>.value( + _FakeFileExistsResult_0( + this, + Invocation.method(#fileExists, [url]), + ), + ), + ) + as _i4.Future<_i2.FileExistsResult>); + + @override + _i4.Future fileModificationDate(String? url) => + (super.noSuchMethod( + Invocation.method(#fileModificationDate, [url]), + returnValue: _i4.Future.value(), + ) + as _i4.Future); + + @override + _i4.Future fileSize(String? url) => + (super.noSuchMethod( + Invocation.method(#fileSize, [url]), + returnValue: _i4.Future.value(), + ) + as _i4.Future); + + @override + _i4.Future> list(String? url) => + (super.noSuchMethod( + Invocation.method(#list, [url]), + returnValue: _i4.Future>.value([]), + ) + as _i4.Future>); +} From 97f60a65abe02405484dde2964866b9c7c68ff58 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 22 Jan 2026 20:26:09 -0500 Subject: [PATCH 108/398] add stuff and stuff --- .../Classes/CrossFileDarwinPlugin.swift | 4 +- ...Delegate.swift => ProxyAPIRegistrar.swift} | 14 +- .../Tests/CrossFileDarwinApiTests.swift | 5 + .../darwin/Tests/FileHandleTests.swift | 151 ++++++++++++++++++ .../darwin/Tests/TestBinaryMessenger.swift | 33 ++++ .../darwin/Tests/TestProxyAPIRegistrar.swift | 11 ++ .../example/assets/hello.txt | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 18 ++- .../ios/RunnerTests/FileHandleTests.swift | 87 ---------- .../example/ios/RunnerTests/RunnerTests.swift | 23 +-- .../cross_file_darwin/example/pubspec.yaml | 2 + 11 files changed, 236 insertions(+), 113 deletions(-) rename packages/cross_file/cross_file_darwin/darwin/Classes/{ProxyAPIDelegate.swift => ProxyAPIRegistrar.swift} (55%) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift create mode 100644 packages/cross_file/cross_file_darwin/example/assets/hello.txt delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift index 98c682d267e7..21a87fe122ed 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift @@ -14,8 +14,8 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { var proxyApiRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar? init(binaryMessenger: FlutterBinaryMessenger) { - proxyApiRegistrar = CrossFileDarwinApisPigeonProxyApiRegistrar( - binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) + proxyApiRegistrar = ProxyAPIRegistrar( + binaryMessenger: binaryMessenger) proxyApiRegistrar?.setUp() } diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift similarity index 55% rename from packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift rename to packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift index c868ddc53f67..bf01f5e8e29f 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift @@ -2,19 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Flutter import Foundation -/// Implementation of `CrossFileDarwinApisPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation -/// and any additional resources needed by an implementation. -open class ProxyApiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { - /// Creates an error when the constructor of a class returns null. +/// Implementation of `CrossFileDarwinApisPigeonProxyApiRegistrar` that provides any additional resources needed by API implementations. +open class ProxyAPIRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar { + init(binaryMessenger: FlutterBinaryMessenger) { + super.init(binaryMessenger: binaryMessenger, apiDelegate: ProxyAPIDelegate()) + } + func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { return PigeonError( code: "ConstructorReturnedNullError", message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", details: nil) } +} +/// Implementation of `WebKitLibraryPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation. +open class ProxyAPIDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle { diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift new file mode 100644 index 000000000000..b3cd65ac71dc --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -0,0 +1,5 @@ +// +// Created by Maurice Parrish on 1/21/26. +// + +import Foundation diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift new file mode 100644 index 000000000000..4fe8e8e92f58 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift @@ -0,0 +1,151 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import Testing + +@testable import cross_file_darwin + +class FileHandleTests { + @Test func forReadingFromUrl() { + let registrar = TestProxyAPIRegistrar() + let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + + let assetFilePath: String = FlutterDartProject.lookupKey(forAsset: "hello.txt") +// let a = Bundle(for: FileHandleTests.self).pat +// forResource: (assetFilePath as NSString).deletingPathExtension, +// withExtension: (assetFilePath as NSString).pathExtension) + let b = Bundle(for: FileHandleTests.self) + let a = b.path(forResource: (assetFilePath as NSString).deletingPathExtension, ofType: (assetFilePath as NSString).pathExtension) + print((assetFilePath as NSString).deletingPathExtension) + print((assetFilePath as NSString).pathExtension) + + //let a = urlForAsset()! + + let instance = try? api.pigeonDelegate.forReadingAtPath(pigeonApi: api, path: a!) + #expect(instance != nil) + } + + // @Test func testReadUpToCount() { + // let registrar = TestProxyAPIRegistrar() + // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + // + // let instance = TestFileHandle() + // let count = 0 + // let value = try? api.pigeonDelegate.readUpToCount( + // pigeonApi: api, pigeonInstance: instance, count: Int64(count)) + // + // XCTAssertEqual(instance.readUpToCountArgs, [count]) + // XCTAssertEqual(value, instance.readUpToCount(count: count)) + // } + // + // @Test func testReadToEnd() { + // let registrar = TestProxyAPIRegistrar() + // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + // + // let instance = TestFileHandle() + // let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance) + // + // XCTAssertTrue(instance.readToEndCalled) + // XCTAssertEqual(value, instance.readToEnd()) + // } + // + // @Test func testSeek() { + // let registrar = TestProxyAPIRegistrar() + // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + // + // let instance = TestFileHandle() + // let offset = 0 + // let value = try? api.pigeonDelegate.seek( + // pigeonApi: api, pigeonInstance: instance, offset: offset) + // + // XCTAssertEqual(instance.seekArgs, [offset]) + // XCTAssertEqual(value, instance.seek(offset: offset)) + // } + // + // @Test func testClose() { + // let registrar = TestProxyAPIRegistrar() + // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) + // + // let instance = TestFileHandle() + // try? api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: instance) + // + // XCTAssertTrue(instance.closeCalled) + // } + + func urlForAsset() -> URL? { + let assetFilePath: String? = FlutterDartProject.lookupKey(forAsset: "assets/index.html") + + guard let assetFilePath = assetFilePath else { + return nil + } + +// print("hello") +// print(FlutterDartProject.lookupKey(forAsset: "assets/index.html")) + + var url: URL? = TestBundle().url( + forResource: (assetFilePath as NSString).deletingPathExtension, + withExtension: (assetFilePath as NSString).pathExtension) + + print(url ?? "open") + + #if os(macOS) + // See https://github.com/flutter/flutter/issues/135302 + // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. + if url == nil { + url = URL(string: assetFilePath, relativeTo: bundle.bundleURL) + } + #endif + + return url + } +} + +class TestBundle: Bundle, @unchecked Sendable { + override func url(forResource name: String?, withExtension ext: String?) -> URL? { + return URL(string: "assets/index.html")! + } +} + +class TestFileHandle: FileHandle, @unchecked Sendable { + var readUpToCountArgs: [AnyHashable?]? = nil + var readToEndCalled = false + var seekArgs: [AnyHashable?]? = nil + var closeCalled = false + + // func read(upToCount count: Int) throws -> Data? { + // readUpToCountArgs = [count] + // return byteArrayOf(0xA1.toByte()) + // } + + // func hello(apple: TestFileHandle) throws -> Data? { + // readToEndCalled = true + // } + + override func seek(toOffset offset: UInt64) throws { + seekArgs = [offset] + } + + override func close() throws { + closeCalled = true + } +} + +//extension TestFileHandle { +// @_dynamicReplacement(for:readToEnd()) +// dynamic func a() throws -> Data? { +// +// } +// +// @_dynamicReplacement(for:close()) +// dynamic func b() throws { +// +// } +//} + +//extension TestFileHandle { +// @objc override func readToEnd() throws -> Data? { +// readToEndCalled = true +// } +//} diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift new file mode 100644 index 000000000000..c40727acb44d --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift @@ -0,0 +1,33 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +class TestBinaryMessenger: NSObject, FlutterBinaryMessenger { + func send(onChannel channel: String, message: Data?) { + + } + + func send( + onChannel channel: String, message: Data?, binaryReply callback: FlutterBinaryReply? = nil + ) { + + } + + func setMessageHandlerOnChannel( + _ channel: String, binaryMessageHandler handler: FlutterBinaryMessageHandler? = nil + ) -> FlutterBinaryMessengerConnection { + return 0 + } + + func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) { + + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift new file mode 100644 index 000000000000..a897f9008968 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift @@ -0,0 +1,11 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +@testable import cross_file_darwin + +class TestProxyAPIRegistrar: ProxyAPIRegistrar { + init() { + super.init(binaryMessenger: TestBinaryMessenger()) + } +} diff --git a/packages/cross_file/cross_file_darwin/example/assets/hello.txt b/packages/cross_file/cross_file_darwin/example/assets/hello.txt new file mode 100644 index 000000000000..b45ef6fec895 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/assets/hello.txt @@ -0,0 +1 @@ +Hello, World! \ No newline at end of file diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 6b7b7966ab19..cbad8c8e53ea 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -14,6 +14,10 @@ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */; }; + 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */; }; + 8F2171F82F21A5270014CE68 /* FileHandleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */; }; + 8F2171FB2F2295120014CE68 /* TestBinaryMessenger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */; }; + 8F2171FC2F2295120014CE68 /* TestProxyAPIRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -56,6 +60,10 @@ 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = ""; }; + 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FileHandleTests.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift; sourceTree = ""; }; + 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestBinaryMessenger.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift; sourceTree = ""; }; + 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = ""; }; 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -92,6 +100,10 @@ 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( + 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */, + 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */, + 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */, + 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */, 331C807B294A618700263BE5 /* RunnerTests.swift */, ); path = RunnerTests; @@ -164,7 +176,6 @@ 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */, 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -373,6 +384,10 @@ buildActionMask = 2147483647; files = ( 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */, + 8F2171F82F21A5270014CE68 /* FileHandleTests.swift in Sources */, + 8F2171FB2F2295120014CE68 /* TestBinaryMessenger.swift in Sources */, + 8F2171FC2F2295120014CE68 /* TestProxyAPIRegistrar.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -497,6 +512,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = PT2QK76LGP; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift deleted file mode 100644 index 8b9b5b043511..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/FileHandleTests.swift +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import XCTest - -@testable import cross_file_darwin - -class FileHandleTests: XCTestCase { - func testForReadingFromUrl() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = try? api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: "myString") - XCTAssertNotNil(instance) - } - - func testReadUpToCount() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - let count = 0 - let value = try? api.pigeonDelegate.readUpToCount( - pigeonApi: api, pigeonInstance: instance, count: count) - - XCTAssertEqual(instance.readUpToCountArgs, [count]) - XCTAssertEqual(value, instance.readUpToCount(count: count)) - } - - func testReadToEnd() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance) - - XCTAssertTrue(instance.readToEndCalled) - XCTAssertEqual(value, instance.readToEnd()) - } - - func testSeek() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - let offset = 0 - let value = try? api.pigeonDelegate.seek( - pigeonApi: api, pigeonInstance: instance, offset: offset) - - XCTAssertEqual(instance.seekArgs, [offset]) - XCTAssertEqual(value, instance.seek(offset: offset)) - } - - func testClose() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - try? api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: instance) - - XCTAssertTrue(instance.closeCalled) - } - -} -class TestFileHandle: FileHandle { - var readUpToCountArgs: [AnyHashable?]? = nil - var readToEndCalled = false - var seekArgs: [AnyHashable?]? = nil - var closeCalled = false - - override func readUpToCount() { - readUpToCountArgs = [count] - return byteArrayOf(0xA1.toByte()) - } - override func readToEnd() { - readToEndCalled = true - } - override func seek() { - seekArgs = [offset] - return 0 - } - override func close() { - closeCalled = true - } -} diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift index 749eeb986e79..ea8b210b8523 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift @@ -1,26 +1,11 @@ import Flutter +import Testing import UIKit -import XCTest @testable import cross_file_darwin -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - -class RunnerTests: XCTestCase { - - func testGetPlatformVersion() { - let plugin = CrossFileDarwinPlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) +struct RunnerTests { + @Test func testGetPlatform() { + #expect(true == true) } - } diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index f2fb299676c8..e42ac86165c9 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -29,3 +29,5 @@ dev_dependencies: flutter: uses-material-design: true + assets: + - assets/hello.txt From bfb9e0adaee7cbaec6f8c0fa69240545d9800e23 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 26 Jan 2026 12:48:03 -0700 Subject: [PATCH 109/398] cross file impl --- .../cross_file/lib/src/cross_directory.dart | 111 ++++++++++++++++++ .../cross_file/lib/src/cross_file.dart | 28 ++--- .../cross_file/lib/src/cross_file_entity.dart | 3 +- .../src/scoped_storage_cross_directory.dart | 75 ++++++++++++ ...le.dart => scoped_storage_cross_file.dart} | 44 +++---- 5 files changed, 223 insertions(+), 38 deletions(-) create mode 100644 packages/cross_file/cross_file/lib/src/cross_directory.dart create mode 100644 packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart rename packages/cross_file/cross_file/lib/src/{shared_storage_cross_file.dart => scoped_storage_cross_file.dart} (52%) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart new file mode 100644 index 000000000000..758123553ae7 --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -0,0 +1,111 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:meta/meta.dart'; + +import 'cross_file.dart'; +import 'cross_file_entity.dart'; +import 'scoped_storage_cross_directory.dart'; +import 'scoped_storage_cross_file.dart'; + +/// A reference to a directory (or folder) on the file system. +/// +/// Note: Not all platforms support directories. +/// +/// ## Platform-Specific Features +/// This class contains an underlying implementation provided by the current +/// platform. Once a platform implementation is imported, the examples below +/// can be followed to use features provided by a platform's implementation. +/// +/// {@macro cross_file.XDirectory.fromCreationParams} +/// +/// Below is an example of accessing the platform-specific extension for +/// the dart:io implementation of `cross_file`: +/// +/// ```dart +/// final XDirectory dir = XFile('my/docs/'); +/// +/// final IOXDirectoryExtension? ioExtension = file.maybeGetExtension(); +/// if (ioExtension != null) { +/// print(ioExtension.directory.path); +/// } +/// ``` +@immutable +class XDirectory extends XFileEntity { + /// Constructs a [XDirectory]. + /// + /// See [XDirectory.fromCreationParams] for setting parameters for a + /// specific platform. + XDirectory(String uri) + : this.fromCreationParams(PlatformXDirectoryCreationParams(uri: uri)); + + /// Constructs a [XDirectory] from creation params for a specific platform. + /// + /// {@template cross_file.XDirectory.fromCreationParams} + /// Below is an example of setting platform-specific creation parameters for + /// the dart:io implementation of `cross_file`: + /// + /// ```dart + /// var params = const PlatformXDirectoryCreationParams(uri: 'my/docs/'); + /// + /// if (CrossFilePlatform.instance is CrossFileIO) { + /// params = IOXDirectoryCreationParams.fromCreationParams( + /// params, + /// ); + /// } + /// + /// final dir = XDirectory.fromCreationParams(params); + /// ``` + /// {@endtemplate} + XDirectory.fromCreationParams(PlatformXDirectoryCreationParams params) + : this.fromPlatform(PlatformXDirectory(params)); + + /// Constructs a [XDirectory] from a specific platform implementation. + const XDirectory.fromPlatform(PlatformXDirectory super.platform); + + /// Implementation of [PlatformXDirectory] for the current platform. + @override + PlatformXDirectory get platform => super.platform as PlatformXDirectory; + + /// Provides a nonnull platform class extension. + /// + /// Will throw an exception if the specified platform extension can not be + /// returned. + S getExtension() { + return platform.extension! as S; + } + + /// Attempt to provide the platform class extension. + /// + /// Returns null if the specified platform extension cannot be retrieved. + S? maybeGetExtension() { + return platform.extension is S ? platform.extension! as S : null; + } + + /// Lists the sub-directories and files of this directory. + Stream list() { + return platform.list(ListParams()).map(( + PlatformXFileEntity entity, + ) { + switch (entity) { + case PlatformXFile(): + if (entity case PlatformScopedStorageXFile()) { + return ScopedStorageXFile.fromPlatform(entity); + } + return XFile.fromPlatform(entity); + case PlatformXDirectory(): + if (entity case PlatformScopedStorageXDirectory()) { + return ScopedStorageXDirectory.fromPlatform(entity); + } + return XDirectory.fromPlatform(entity); + } + + return XFileEntity(entity); + }); + } +} diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index e4d60330f383..bae51c72dc77 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -17,7 +17,7 @@ import 'cross_file_entity.dart'; /// platform. Once a platform implementation is imported, the examples below /// can be followed to use features provided by a platform's implementation. /// -/// {@macro cross_file.XFile.fromPlatformCreationParams} +/// {@macro cross_file.XFile.fromCreationParams} /// /// Below is an example of accessing the platform-specific extension for /// the dart:io implementation of `cross_file`: @@ -25,7 +25,7 @@ import 'cross_file_entity.dart'; /// ```dart /// final XFile file = XFile('my/file.txt'); /// -/// final IOXFileExtension? ioExtension = file.maybeGetPlatformExtension(); +/// final IOXFileExtension? ioExtension = file.maybeGetExtension(); /// if (ioExtension != null) { /// print(ioExtension.file.path); /// } @@ -34,14 +34,14 @@ import 'cross_file_entity.dart'; class XFile extends XFileEntity { /// Constructs a [XFile]. /// - /// See [XFile.fromPlatformCreationParams] for setting parameters for a + /// See [XFile.fromCreationParams] for setting parameters for a /// specific platform. XFile(String uri) - : this.fromPlatformCreationParams(PlatformXFileCreationParams(uri: uri)); + : this.fromCreationParams(PlatformXFileCreationParams(uri: uri)); - /// Constructs an [XFile] from creation params for a specific platform. + /// Constructs a [XFile] from creation params for a specific platform. /// - /// {@template cross_file.XFile.fromPlatformCreationParams} + /// {@template cross_file.XFile.fromCreationParams} /// Below is an example of setting platform-specific creation parameters for /// the dart:io implementation of `cross_file`: /// @@ -57,7 +57,7 @@ class XFile extends XFileEntity { /// final file = XFile.fromCreationParams(params); /// ``` /// {@endtemplate} - XFile.fromPlatformCreationParams(PlatformXFileCreationParams params) + XFile.fromCreationParams(PlatformXFileCreationParams params) : this.fromPlatform(PlatformXFile(params)); /// Constructs a [XFile] from a specific platform implementation. @@ -71,27 +71,25 @@ class XFile extends XFileEntity { /// /// Will throw an exception if the specified platform extension can not be /// returned. - S getPlatformExtension() { + S getExtension() { return platform.extension! as S; } /// Attempt to provide the platform class extension. /// /// Returns null if the specified platform extension cannot be retrieved. - S? maybeGetPlatformExtension() { + S? maybeGetExtension() { return platform.extension is S ? platform.extension! as S : null; } /// Date and time when the resource was last modified, if the information is /// available. - /// - /// Platforms may throw an exception if the information is not available. - Future lastModified() => platform.lastModified(); + Future lastModified() => platform.lastModified(); /// The length of the data represented by this uri, in bytes. /// - /// Platforms may throw an exception if the information is not available. - Future length() => platform.length(); + /// Returns null if the information is not available. + Future length() => platform.length(); /// Whether the resource represented by this reference can be read. Future canRead() => platform.canRead(); @@ -106,7 +104,7 @@ class XFile extends XFileEntity { /// /// Platforms may throw an exception if there is an error opening or reading /// the resource. - Stream> openRead([int? start, int? end]) => + Stream openRead([int? start, int? end]) => platform.openRead(start, end); /// Reads the entire resource contents as a list of bytes. diff --git a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart index 4c5d271d80f8..8fef86fec614 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart @@ -7,8 +7,9 @@ import 'package:meta/meta.dart'; /// The common superclass for [XFile] and [XDirectory]. @immutable -abstract class XFileEntity { +class XFileEntity { /// Constructs a [XFileEntity]. + @protected const XFileEntity(this.platform); /// Implementation of [XFileEntity] for the current platform. diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart new file mode 100644 index 000000000000..4478e200b838 --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -0,0 +1,75 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart' show immutable; + +import 'cross_directory.dart'; + +/// A reference to a directory (or folder) on the file system within a devices +/// scoped storage. +/// +/// ## Platform-Specific Features +/// This class contains an underlying implementation provided by the current +/// platform. Once a platform implementation is imported, the examples below +/// can be followed to use features provided by a platform's implementation. +/// +/// {@macro cross_file.ScopedStorageXDirectory.fromCreationParams} +/// +/// Below is an example of accessing the platform-specific extension for +/// the Android implementation of `cross_file`: +/// +/// ```dart +/// final ScopedStorageXDirectory directory = XDirectory('my/dir'); +/// +/// final AndroidScopedStorageXDirectoryExtension? androidExtension = +/// file.maybeGetExtension(); +/// if (androidExtension != null) { +/// print(androidExtension.name()); +/// } +/// ``` +@immutable +class ScopedStorageXDirectory extends XDirectory { + /// Constructs a [ScopedStorageXDirectory]. + /// + /// See [ScopedStorageXDirectory.fromCreationParams] for setting parameters + /// for a specific platform. + ScopedStorageXDirectory(String uri) + : this.fromCreationParams( + PlatformScopedStorageXDirectoryCreationParams(uri: uri), + ); + + /// Constructs a [ScopedStorageXDirectory] from creation params for a specific + /// platform. + /// + /// {@template cross_file.ScopedStorageXDirectory.fromCreationParams} + /// Below is an example of setting platform-specific creation parameters for + /// the Android implementation of `cross_file`: + /// + /// ```dart + /// var params = const PlatformXDirectoryCreationParams(uri: 'my/file.txt'); + /// + /// if (CrossFilePlatform.instance is CrossFileAndroid) { + /// params = AndroidScopedStorageXDirectoryCreationParams.fromCreationParams( + /// params, + /// ); + /// } + /// + /// final file = ScopedStorageXDirectory.fromCreationParams(params); + /// ``` + /// {@endtemplate} + ScopedStorageXDirectory.fromCreationParams( + PlatformScopedStorageXDirectoryCreationParams params, + ) : this.fromPlatform(PlatformScopedStorageXDirectory(params)); + + /// Constructs a [ScopedStorageXDirectory] from a specific platform + /// implementation. + const ScopedStorageXDirectory.fromPlatform( + PlatformScopedStorageXDirectory super.platform, + ) : super.fromPlatform(); + + @override + PlatformScopedStorageXDirectory get platform => + super.platform as PlatformScopedStorageXDirectory; +} diff --git a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart similarity index 52% rename from packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart rename to packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index b364046ff6a6..5b21777f5053 100644 --- a/packages/cross_file/cross_file/lib/src/shared_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -14,35 +14,35 @@ import 'cross_file.dart'; /// platform. Once a platform implementation is imported, the examples below /// can be followed to use features provided by a platform's implementation. /// -/// {@macro cross_file.XFile.fromPlatformCreationParams} +/// {@macro cross_file.ScopedStorageXFile.fromCreationParams} /// /// Below is an example of accessing the platform-specific extension for /// the Android implementation of `cross_file`: /// /// ```dart -/// final SharedStorageXFile file = XFile('my/file.txt'); +/// final ScopedStorageXFile file = XFile('my/file.txt'); /// -/// final AndroidSharedStorageXFileExtension? androidExtension = -/// file.maybeGetPlatformExtension(); +/// final AndroidScopedStorageXFileExtension? androidExtension = +/// file.maybeGetExtension(); /// if (androidExtension != null) { -/// print(androidExtension.file.path); +/// print(androidExtension.name()); /// } /// ``` @immutable -class SharedStorageXFile extends XFile { - /// Constructs a [SharedStorageXFile]. +class ScopedStorageXFile extends XFile { + /// Constructs a [ScopedStorageXFile]. /// - /// See [SharedStorageXFile.fromPlatformCreationParams] for setting parameters + /// See [ScopedStorageXFile.fromCreationParams] for setting parameters /// for a specific platform. - SharedStorageXFile(String uri) - : this.fromPlatformCreationParams( - PlatformSharedStorageXFileCreationParams(uri: uri), + ScopedStorageXFile(String uri) + : this.fromCreationParams( + PlatformScopedStorageXFileCreationParams(uri: uri), ); - /// Constructs a [SharedStorageXFile] from creation params for a specific + /// Constructs a [ScopedStorageXFile] from creation params for a specific /// platform. /// - /// {@template cross_file.SharedStorageXFile.fromPlatformCreationParams} + /// {@template cross_file.ScopedStorageXFile.fromCreationParams} /// Below is an example of setting platform-specific creation parameters for /// the Android implementation of `cross_file`: /// @@ -50,23 +50,23 @@ class SharedStorageXFile extends XFile { /// var params = const PlatformXFileCreationParams(uri: 'my/file.txt'); /// /// if (CrossFilePlatform.instance is CrossFileAndroid) { - /// params = AndroidSharedStorageXFileCreationParams.fromCreationParams( + /// params = AndroidScopedStorageXFileCreationParams.fromCreationParams( /// params, /// ); /// } /// - /// final file = SharedStorageXFile.fromCreationParams(params); + /// final file = ScopedStorageXFile.fromCreationParams(params); /// ``` /// {@endtemplate} - SharedStorageXFile.fromPlatformCreationParams( - PlatformSharedStorageXFileCreationParams params, - ) : this.fromPlatform(PlatformSharedStorageXFile(params)); + ScopedStorageXFile.fromCreationParams( + PlatformScopedStorageXFileCreationParams params, + ) : this.fromPlatform(PlatformScopedStorageXFile(params)); - /// Constructs a [SharedStorageXFile] from a specific platform implementation. - const SharedStorageXFile.fromPlatform(PlatformSharedStorageXFile super.platform) + /// Constructs a [ScopedStorageXFile] from a specific platform implementation. + const ScopedStorageXFile.fromPlatform(PlatformScopedStorageXFile super.platform) : super.fromPlatform(); @override - PlatformSharedStorageXFile get platform => - super.platform as PlatformSharedStorageXFile; + PlatformScopedStorageXFile get platform => + super.platform as PlatformScopedStorageXFile; } From ae1aaf394fb03f6d2a8fd7a60850f9df74809a2f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 26 Jan 2026 12:51:25 -0700 Subject: [PATCH 110/398] add context for android example --- .../cross_file/lib/src/scoped_storage_cross_directory.dart | 2 +- .../cross_file/lib/src/scoped_storage_cross_file.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index 4478e200b838..a6644f78036e 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -48,7 +48,7 @@ class ScopedStorageXDirectory extends XDirectory { /// the Android implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformXDirectoryCreationParams(uri: 'my/file.txt'); + /// var params = const PlatformXDirectoryCreationParams(uri: 'context://my/docs'); /// /// if (CrossFilePlatform.instance is CrossFileAndroid) { /// params = AndroidScopedStorageXDirectoryCreationParams.fromCreationParams( diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 5b21777f5053..870e8c8ec072 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -20,7 +20,7 @@ import 'cross_file.dart'; /// the Android implementation of `cross_file`: /// /// ```dart -/// final ScopedStorageXFile file = XFile('my/file.txt'); +/// final ScopedStorageXFile file = XFile('context://my/file.txt'); /// /// final AndroidScopedStorageXFileExtension? androidExtension = /// file.maybeGetExtension(); From e41934225aa0c4697dd1d9d6b939fd1991c918f1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 15:22:02 -0700 Subject: [PATCH 111/398] update to new impl --- .../cross_file/example/lib/main.dart | 104 ++++++++ .../cross_file/example/pubspec.yaml | 20 +- .../cross_file/cross_file/lib/cross_file.dart | 6 +- .../cross_file/lib/src/cross_directory.dart | 5 +- .../cross_file/lib/src/cross_file.dart | 3 +- .../cross_file/lib/src/cross_file_entity.dart | 2 +- .../cross_file/lib/src/types/base.dart | 89 ------- .../cross_file/lib/src/types/html.dart | 234 ------------------ .../cross_file/lib/src/types/interface.dart | 65 ----- .../cross_file/lib/src/types/io.dart | 141 ----------- .../lib/src/web_helpers/web_helpers.dart | 37 --- .../cross_file/cross_file/lib/src/x_file.dart | 7 - packages/cross_file/cross_file/pubspec.yaml | 32 ++- 13 files changed, 158 insertions(+), 587 deletions(-) create mode 100644 packages/cross_file/cross_file/example/lib/main.dart delete mode 100644 packages/cross_file/cross_file/lib/src/types/base.dart delete mode 100644 packages/cross_file/cross_file/lib/src/types/html.dart delete mode 100644 packages/cross_file/cross_file/lib/src/types/interface.dart delete mode 100644 packages/cross_file/cross_file/lib/src/types/io.dart delete mode 100644 packages/cross_file/cross_file/lib/src/web_helpers/web_helpers.dart delete mode 100644 packages/cross_file/cross_file/lib/src/x_file.dart diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart new file mode 100644 index 000000000000..24ef4b992d9e --- /dev/null +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -0,0 +1,104 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector/file_selector.dart'; +import 'package:cross_file/cross_file.dart'; +import 'package:flutter/material.dart'; +import 'package:mime/mime.dart' as mime; + +void main() { + runApp(const MaterialApp(home: FileOpenScreen())); +} + +/// Example screen to open a file selector and display it. +class FileOpenScreen extends StatelessWidget { + /// Constructs a [FileOpenScreen]. + const FileOpenScreen({super.key}); + + Future _openFile(BuildContext context) async { + final XFile? file = await openFile(); + + final String? fileName = await file.name() ?? file.uri; + + if (!context.mounted) { + return; + } + + if (file case final XFile file) { + switch (mime.lookupMimeType(fileName)) { + case final String mimeType when mimeType.startsWith('text'): + await showDialog( + context: context, + builder: (BuildContext context) => TextDisplay(file), + ); + case final String mimeType when mimeType.startsWith('image'): + case final String mimeType when mimeType.startsWith('application'): + case null: + debugPrint('Unsupported file type: ${file.path}'); + return; + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Open a File'), + backgroundColor: Colors.blue, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ], + ), + ), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay(this.file, {super.key}); + + /// The file. + final XFile file; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(file.path), + content: Scrollbar( + child: SingleChildScrollView( + child: FutureBuilder( + future: file.readAsString(), + builder: (_, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return Text(snapshot.data!); + } else { + return const CircularProgressIndicator(); + } + }, + ), + ), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index aec48e35e3ce..6302aa15b8e9 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -3,7 +3,8 @@ description: Demonstrates how to use cross files. publish_to: none environment: - sdk: ^3.8.0 + sdk: ^3.9.0 + flutter: ">=3.35.0" dependencies: cross_file: @@ -13,6 +14,21 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ + file_selector: ^1.1.0 + flutter: + sdk: flutter + flutter_driver: + sdk: flutter + mime: ^2.0.0 + video_player: ^2.8.6 dev_dependencies: - test: ^1.24.0 + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true + assets: + - assets/hello.txt diff --git a/packages/cross_file/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart index f0fc41b9919e..afda4f9eb36b 100644 --- a/packages/cross_file/cross_file/lib/cross_file.dart +++ b/packages/cross_file/cross_file/lib/cross_file.dart @@ -2,4 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -export 'src/x_file.dart'; +export 'src/cross_directory.dart'; +export 'src/cross_file.dart'; +export 'src/cross_file_entity.dart'; +export 'src/scoped_storage_cross_directory.dart'; +export 'src/scoped_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 758123553ae7..2adbb3207e31 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -2,11 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:convert'; -import 'dart:typed_data'; - import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:meta/meta.dart'; +import 'package:flutter/foundation.dart'; import 'cross_file.dart'; import 'cross_file_entity.dart'; diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index bae51c72dc77..23a6d136ecb4 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -3,10 +3,9 @@ // found in the LICENSE file. import 'dart:convert'; -import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:meta/meta.dart'; +import 'package:flutter/foundation.dart'; import 'cross_file_entity.dart'; diff --git a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart index 8fef86fec614..c6eb1152f8d5 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:meta/meta.dart'; +import 'package:flutter/foundation.dart'; /// The common superclass for [XFile] and [XDirectory]. @immutable diff --git a/packages/cross_file/cross_file/lib/src/types/base.dart b/packages/cross_file/cross_file/lib/src/types/base.dart deleted file mode 100644 index b3fb82ea4063..000000000000 --- a/packages/cross_file/cross_file/lib/src/types/base.dart +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:typed_data'; - -/// The interface for a CrossFile. -/// -/// A CrossFile is a container that wraps the path of a selected -/// file by the user and (in some platforms, like web) the bytes -/// with the contents of the file. -/// -/// This class is a very limited subset of dart:io [File], so all -/// the methods should seem familiar. -abstract class XFileBase { - /// Construct a CrossFile - // ignore: avoid_unused_constructor_parameters - XFileBase(String? path); - - /// Save the CrossFile at the indicated file path. - Future saveTo(String path) { - throw UnimplementedError('saveTo has not been implemented.'); - } - - /// Get the path of the picked file. - /// - /// This should only be used as a backwards-compatibility clutch - /// for mobile apps, or cosmetic reasons only (to show the user - /// the path they've picked). - /// - /// Accessing the data contained in the picked file by its path - /// is platform-dependant (and won't work on web), so use the - /// byte getters in the CrossFile instance instead. - String get path { - throw UnimplementedError('.path has not been implemented.'); - } - - /// The name of the file as it was selected by the user in their device. - /// - /// For non-web implementation, this represents the last part of the filesystem path. - /// - /// Use only for cosmetic reasons, do not try to use this as a path. - String get name { - throw UnimplementedError('.name has not been implemented.'); - } - - /// For web, it may be necessary for a file to know its MIME type. - String? get mimeType { - throw UnimplementedError('.mimeType has not been implemented.'); - } - - /// Get the length of the file. Returns a `Future` that completes with the length in bytes. - Future length() { - throw UnimplementedError('.length() has not been implemented.'); - } - - /// Asynchronously read the entire file contents as a string using the given [Encoding]. - /// - /// By default, `encoding` is [utf8]. - /// - /// Throws Exception if the operation fails. - Future readAsString({Encoding encoding = utf8}) { - throw UnimplementedError('readAsString() has not been implemented.'); - } - - /// Asynchronously read the entire file contents as a list of bytes. - /// - /// Throws Exception if the operation fails. - Future readAsBytes() { - throw UnimplementedError('readAsBytes() has not been implemented.'); - } - - /// Create a new independent [Stream] for the contents of this file. - /// - /// If `start` is present, the file will be read from byte-offset `start`. Otherwise from the beginning (index 0). - /// - /// If `end` is present, only up to byte-index `end` will be read. Otherwise, until end of file. - /// - /// In order to make sure that system resources are freed, the stream must be read to completion or the subscription on the stream must be cancelled. - Stream openRead([int? start, int? end]) { - throw UnimplementedError('openRead() has not been implemented.'); - } - - /// Get the last-modified time for the CrossFile - Future lastModified() { - throw UnimplementedError('lastModified() has not been implemented.'); - } -} diff --git a/packages/cross_file/cross_file/lib/src/types/html.dart b/packages/cross_file/cross_file/lib/src/types/html.dart deleted file mode 100644 index 9c85e1511b85..000000000000 --- a/packages/cross_file/cross_file/lib/src/types/html.dart +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:js_interop'; -import 'dart:typed_data'; - -import 'package:meta/meta.dart'; -import 'package:web/web.dart'; - -import '../web_helpers/web_helpers.dart'; -import 'base.dart'; - -// Four Gigabytes, in bytes. -const int _fourGigabytes = 4 * 1024 * 1024 * 1024; - -/// A CrossFile that works on web. -/// -/// It wraps the bytes of a selected file. -class XFile extends XFileBase { - /// Construct a CrossFile object from its ObjectUrl. - /// - /// Optionally, this can be initialized with `bytes` and `length` - /// so no http requests are performed to retrieve files later. - /// - /// `name` needs to be passed from the outside, since it's only available - /// while handling [html.File]s (when the ObjectUrl is created). - // ignore: use_super_parameters - XFile( - String path, { - String? mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, - @visibleForTesting CrossFileTestOverrides? overrides, - }) : _mimeType = mimeType, - _path = path, - _length = length, - _overrides = overrides, - _lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0), - _name = name ?? '', - super(path) { - // Cache `bytes` as Blob, if passed. - if (bytes != null) { - _browserBlob = _createBlobFromBytes(bytes, mimeType); - } - } - - /// Construct an CrossFile from its data - XFile.fromData( - Uint8List bytes, { - String? mimeType, - String? name, - int? length, - DateTime? lastModified, - String? path, - @visibleForTesting CrossFileTestOverrides? overrides, - }) : _mimeType = mimeType, - _length = length, - _overrides = overrides, - _lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0), - _name = name ?? '', - super(path) { - _browserBlob = _createBlobFromBytes(bytes, mimeType); - _path = URL.createObjectURL(_browserBlob!); - } - - // Initializes a Blob from a bunch of `bytes` and an optional `mimeType`. - Blob _createBlobFromBytes(Uint8List bytes, String? mimeType) { - return (mimeType == null) - ? Blob([bytes.toJS].toJS) - : Blob( - [bytes.toJS].toJS, - BlobPropertyBag(type: mimeType), - ); - } - - // Overridable (meta) data that can be specified by the constructors. - - // MimeType of the file (eg: "image/gif"). - final String? _mimeType; - // Name (with extension) of the file (eg: "anim.gif") - final String _name; - // Path of the file (must be a valid Blob URL, when set manually!) - late String _path; - // The size of the file (in bytes). - final int? _length; - // The time the file was last modified. - final DateTime _lastModified; - - // The link to the binary object in the browser memory (Blob). - // This can be passed in (as `bytes` in the constructor) or derived from - // [_path] with a fetch request. - // (Similar to a (read-only) dart:io File.) - Blob? _browserBlob; - - // An html Element that will be used to trigger a "save as" dialog later. - // TODO(dit): https://github.com/flutter/flutter/issues/91400 Remove this _target. - late Element _target; - - // Overrides for testing - // TODO(dit): https://github.com/flutter/flutter/issues/91400 Remove these _overrides, - // they're only used to Save As... - final CrossFileTestOverrides? _overrides; - - bool get _hasTestOverrides => _overrides != null; - - @override - String? get mimeType => _mimeType; - - @override - String get name => _name; - - @override - String get path => _path; - - @override - Future lastModified() async => _lastModified; - - Future get _blob async { - if (_browserBlob != null) { - return _browserBlob!; - } - - // Attempt to re-hydrate the blob from the `path` via a (local) HttpRequest. - // Note that safari hangs if the Blob is >=4GB, so bail out in that case. - if (isSafari() && _length != null && _length >= _fourGigabytes) { - throw Exception('Safari cannot handle XFiles larger than 4GB.'); - } - - final blobCompleter = Completer(); - - late XMLHttpRequest request; - request = XMLHttpRequest() - ..open('get', path, true) - ..responseType = 'blob' - ..onLoad.listen((ProgressEvent e) { - assert( - request.response != null, - 'The Blob backing this XFile cannot be null!', - ); - blobCompleter.complete(request.response! as Blob); - }) - ..onError.listen((ProgressEvent e) { - if (e.type == 'error') { - blobCompleter.completeError( - Exception('Could not load Blob from its URL. Has it been revoked?'), - ); - } - }) - ..send(); - - return blobCompleter.future; - } - - @override - Future readAsBytes() async { - return _blob.then(_blobToByteBuffer); - } - - @override - Future length() async => _length ?? (await _blob).size; - - @override - Future readAsString({Encoding encoding = utf8}) async { - return readAsBytes().then(encoding.decode); - } - - // TODO(dit): https://github.com/flutter/flutter/issues/91867 Implement openRead properly. - @override - Stream openRead([int? start, int? end]) async* { - final Blob blob = await _blob; - - final Blob slice = blob.slice(start ?? 0, end ?? blob.size, blob.type); - - final Uint8List convertedSlice = await _blobToByteBuffer(slice); - - yield convertedSlice; - } - - // Converts an html Blob object to a Uint8List, through a FileReader. - Future _blobToByteBuffer(Blob blob) async { - final reader = FileReader(); - reader.readAsArrayBuffer(blob); - - await reader.onLoadEnd.first; - - final Uint8List? result = (reader.result as JSArrayBuffer?)?.toDart - .asUint8List(); - - if (result == null) { - throw Exception('Cannot read bytes from Blob. Is it still available?'); - } - - return result; - } - - /// Saves the data of this CrossFile at the location indicated by path. - /// For the web implementation, the path variable is ignored. - // TODO(dit): https://github.com/flutter/flutter/issues/91400 - // Move implementation to web_helpers.dart - @override - Future saveTo(String path) async { - // Create a DOM container where the anchor can be injected. - _target = ensureInitialized('__x_file_dom_element'); - - // Create an tag with the appropriate download attributes and click it - // May be overridden with CrossFileTestOverrides - final HTMLAnchorElement element = _hasTestOverrides - ? _overrides!.createAnchorElement(this.path, name) as HTMLAnchorElement - : createAnchorElement(this.path, name); - - // Clear the children in _target and add an element to click - while (_target.children.length > 0) { - _target.removeChild(_target.children.item(0)!); - } - addElementToContainerAndClick(_target, element); - } -} - -/// Overrides some functions to allow testing -// TODO(dit): https://github.com/flutter/flutter/issues/91400 -// Move this to web_helpers_test.dart -@visibleForTesting -class CrossFileTestOverrides { - /// Default constructor for overrides - CrossFileTestOverrides({required this.createAnchorElement}); - - /// For overriding the creation of the file input element. - Element Function(String href, String suggestedName) createAnchorElement; -} diff --git a/packages/cross_file/cross_file/lib/src/types/interface.dart b/packages/cross_file/cross_file/lib/src/types/interface.dart deleted file mode 100644 index d539b4e2633c..000000000000 --- a/packages/cross_file/cross_file/lib/src/types/interface.dart +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:typed_data'; -import 'package:meta/meta.dart'; - -import './base.dart'; - -// ignore_for_file: avoid_unused_constructor_parameters - -/// A CrossFile is a cross-platform, simplified File abstraction. -/// -/// It wraps the bytes of a selected file, and its (platform-dependant) path. -class XFile extends XFileBase { - /// Construct a CrossFile object from its path. - /// - /// Optionally, this can be initialized with `bytes` and `length` - /// so no http requests are performed to retrieve data later. - /// - /// `name` may be passed from the outside, for those cases where the effective - /// `path` of the file doesn't match what the user sees when selecting it - /// (like in web) - XFile( - String super.path, { - String? mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, - @visibleForTesting CrossFileTestOverrides? overrides, - }) { - throw UnimplementedError( - 'CrossFile is not available in your current platform.', - ); - } - - /// Construct a CrossFile object from its data. - /// - /// On the web, the [path] is ignored if the [bytes] are provided, - /// as the underlying Blob URL is used as the path. - XFile.fromData( - Uint8List bytes, { - String? mimeType, - String? name, - int? length, - DateTime? lastModified, - String? path, - @visibleForTesting CrossFileTestOverrides? overrides, - }) : super(path) { - throw UnimplementedError( - 'CrossFile is not available in your current platform.', - ); - } -} - -/// Overrides some functions of CrossFile for testing purposes -@visibleForTesting -class CrossFileTestOverrides { - /// Default constructor for overrides - CrossFileTestOverrides({required this.createAnchorElement}); - - /// For overriding the creation of the file input element. - dynamic Function(String href, String suggestedName) createAnchorElement; -} diff --git a/packages/cross_file/cross_file/lib/src/types/io.dart b/packages/cross_file/cross_file/lib/src/types/io.dart deleted file mode 100644 index c1931a743a89..000000000000 --- a/packages/cross_file/cross_file/lib/src/types/io.dart +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import './base.dart'; - -// ignore_for_file: avoid_unused_constructor_parameters - -/// A CrossFile backed by a dart:io File. -class XFile extends XFileBase { - /// Construct a CrossFile object backed by a dart:io File. - /// - /// [bytes] is ignored; the parameter exists only to match the web version of - /// the constructor. To construct a dart:io XFile from bytes, use - /// [XFile.fromData]. - /// - /// [name] is ignored; the parameter exists only to match the web version of - /// the constructor. - /// - /// [length] is ignored; the parameter exists only to match the web version of - /// the constructor. - /// - // ignore: use_super_parameters - XFile( - String path, { - String? mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, - }) : _mimeType = mimeType, - _file = File(path), - _bytes = null, - _lastModified = lastModified, - super(path); - - /// Construct an CrossFile from its data - /// - /// [name] is ignored; the parameter exists only to match the web version of - /// the constructor. - XFile.fromData( - Uint8List bytes, { - String? mimeType, - String? path, - String? name, - int? length, - DateTime? lastModified, - }) : _mimeType = mimeType, - _bytes = bytes, - _file = File(path ?? ''), - _length = length, - _lastModified = lastModified, - super(path) { - if (length == null) { - _length = bytes.length; - } - } - - final File _file; - final String? _mimeType; - final DateTime? _lastModified; - int? _length; - - final Uint8List? _bytes; - - @override - Future lastModified() { - if (_lastModified != null) { - return Future.value(_lastModified); - } - // ignore: avoid_slow_async_io - return _file.lastModified(); - } - - @override - Future saveTo(String path) async { - if (_bytes == null) { - await _file.copy(path); - } else { - final fileToSave = File(path); - // TODO(kevmoo): Remove ignore and fix when the MIN Dart SDK is 3.3 - // ignore: unnecessary_non_null_assertion - await fileToSave.writeAsBytes(_bytes!); - } - } - - @override - String? get mimeType => _mimeType; - - @override - String get path => _file.path; - - @override - String get name => _file.path.split(Platform.pathSeparator).last; - - @override - Future length() { - if (_length != null) { - return Future.value(_length); - } - return _file.length(); - } - - @override - Future readAsString({Encoding encoding = utf8}) { - if (_bytes != null) { - // TODO(kevmoo): Remove ignore and fix when the MIN Dart SDK is 3.3 - // ignore: unnecessary_non_null_assertion - return Future.value(String.fromCharCodes(_bytes!)); - } - return _file.readAsString(encoding: encoding); - } - - @override - Future readAsBytes() { - if (_bytes != null) { - return Future.value(_bytes); - } - return _file.readAsBytes(); - } - - Stream _getBytes(int? start, int? end) async* { - final Uint8List bytes = _bytes!; - yield bytes.sublist(start ?? 0, end ?? bytes.length); - } - - @override - Stream openRead([int? start, int? end]) { - if (_bytes != null) { - return _getBytes(start, end); - } else { - return _file - .openRead(start ?? 0, end) - .map((List chunk) => Uint8List.fromList(chunk)); - } - } -} diff --git a/packages/cross_file/cross_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/cross_file/lib/src/web_helpers/web_helpers.dart deleted file mode 100644 index daac03159509..000000000000 --- a/packages/cross_file/cross_file/lib/src/web_helpers/web_helpers.dart +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:web/web.dart'; - -/// Create anchor element with download attribute -HTMLAnchorElement createAnchorElement(String href, String? suggestedName) => - (document.createElement('a') as HTMLAnchorElement) - ..href = href - ..download = suggestedName ?? 'download'; - -/// Add an element to a container and click it -void addElementToContainerAndClick(Element container, HTMLElement element) { - // Add the element and click it - // All previous elements will be removed before adding the new one - container.appendChild(element); - element.click(); -} - -/// Initializes a DOM container where elements can be injected. -Element ensureInitialized(String id) { - Element? target = document.querySelector('#$id'); - if (target == null) { - final Element targetElement = document.createElement('flt-x-file')..id = id; - - document.body!.appendChild(targetElement); - target = targetElement; - } - return target; -} - -/// Determines if the browser is Safari from its vendor string. -/// (This is the same check used in flutter/engine) -bool isSafari() { - return window.navigator.vendor == 'Apple Computer, Inc.'; -} diff --git a/packages/cross_file/cross_file/lib/src/x_file.dart b/packages/cross_file/cross_file/lib/src/x_file.dart deleted file mode 100644 index 0d00d96fd1a3..000000000000 --- a/packages/cross_file/cross_file/lib/src/x_file.dart +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -export 'types/interface.dart' - if (dart.library.js_interop) 'types/html.dart' - if (dart.library.io) 'types/io.dart'; diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index c5df67d97e2a..5ec397183790 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -5,17 +5,41 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 0.3.5+1 environment: - sdk: ^3.8.0 + sdk: ^3.9.0 + flutter: ">=3.35.0" + +flutter: + plugin: + platforms: + android: + default_package: cross_file_android + ios: + default_package: cross_file_darwin + linux: + default_package: cross_file_io + macos: + default_package: cross_file_darwin + web: + default_package: cross_file_web + windows: + default_package: cross_file_io dependencies: + cross_file_android: + path: ../cross_file_android + cross_file_darwin: + path: ../cross_file_darwin + cross_file_io: + path: ../cross_file_io cross_file_platform_interface: path: ../cross_file_platform_interface - meta: ^1.17.0 - web: ">=0.5.1 <2.0.0" + flutter: + sdk: flutter dev_dependencies: + flutter_test: + sdk: flutter path: ^1.8.1 - test: ^1.21.1 topics: - files From 295ea46209079d88896bf97432e9fb797e45b93f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 15:47:00 -0700 Subject: [PATCH 112/398] generally rewrite readme --- packages/cross_file/cross_file/README.md | 85 +++++++++++++------ .../example/lib/readme_excerpts.dart | 14 +-- packages/cross_file/cross_file_web/README.md | 21 +++++ 3 files changed, 85 insertions(+), 35 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index 290295571877..0066b1a90fe1 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -15,49 +15,78 @@ Example: final file = XFile('assets/hello.txt'); print('File information:'); -print('- Path: ${file.path}'); -print('- Name: ${file.name}'); -print('- MIME type: ${file.mimeType}'); +print('- URI: ${file.uri}'); +print('- Name: ${await file.name()}'); -final String fileContent = await file.readAsString(); -print('Content of the file: $fileContent'); +if (await file.canRead()) { + final String fileContent = await file.readAsString(); + debugPrint('Content of the file: $fileContent'); +} ``` You will find links to the API docs on the [pub page](https://pub.dev/packages/cross_file). -## Web Limitations +### Implementation-Specific Features -`XFile` on the web platform is backed by [Blob](https://api.dart.dev/be/180361/dart-html/Blob-class.html) -objects and their URLs. +Classes in this package contain an underlying platform implementation that provides features that +are specific to an implementation. -It seems that Safari hangs when reading Blobs larger than 4GB (your app will stop -without returning any data, or throwing an exception). +To access implementation-specific features, start by adding the platform implementation packages to +your app or package: -This package will attempt to throw an `Exception` before a large file is accessed -from Safari (if its size is known beforehand), so that case can be handled -programmatically. +* **dart:io** [cross_file_io](https://pub.dev/packages/cross_file_io/install) +* **Android Scoped Storage**: [cross_file_android](https://pub.dev/packages/cross_file_android/install) +* **iOS/macOS App Sandbox**: [cross_file_darwin](https://pub.dev/packages/cross_file_darwin/install) +* **Web**: [cross_file_web](https://pub.dev/packages/cross_file_web/install) -### Browser compatibility +Next, add the imports of the implementation packages to your app or package: -[![Data on Global support for Blob constructing](https://caniuse.bitsofco.de/image/blobbuilder.png)](https://caniuse.com/blobbuilder) + +```dart +// Import for Android Scoped Storage features. +import 'package:cross_file_android/cross_file_android.dart'; +// Import for iOS/macOS App Sandbox features. +import 'package:cross_file_darwin/cross_file_darwin.dart'; +``` -[![Data on Global support for Blob URLs](https://caniuse.bitsofco.de/image/bloburls.png)](https://caniuse.com/bloburls) +Now, additional features can be accessed through the platform implementations. Classes +[XFile], [XDirectory], [ScopedStorageXFile], and [ScopedStorageXDirectory] pass their +functionality to a class provided by the current platform. Below are a couple of ways to access +additional functionality provided by the platform and is followed by an example. -## Testing +1. Pass a creation params class provided by a platform implementation to a `fromCreationParams` + constructor (e.g. `XFile.fromCreationParams`, `XDirectory.fromCreationParams`, etc.). +2. Call methods on an implementation of a class by using `getExtension`/`maybeGetExtension` methods (e.g. + `XFile.getExtension`, `XDirectory.maybeGetExtension`, etc.). -This package supports both web and native platforms. Unit tests need to be split -in two separate suites (because native code cannot use `package:web`, and web code -cannot use `dart:io`). +Below is an example of setting additional iOS/macOS and Android parameters on a `XFile`. + + +```dart +var params = const PlatformXFileCreationParams(uri: 'my/file.txt'); -When adding new features, it is likely that tests need to be added for both the -native and web platforms. +if (CrossFilePlatform.instance is CrossFileIO) { + params = IOXFileCreationParams.fromCreationParams( + params, + ); +} + +final file = XFile.fromCreationParams(params); + +final IOXFileExtension? ioExtension = file.maybeGetExtension(); +if (ioExtension != null) { + print(ioExtension.file.path); +} +``` -### Native tests +See https://pub.dev/documentation/cross_file_darwin/latest/cross_file_darwin/cross_file_darwin-library.html +for more details on iOS/macOS App Sandbox features. -Tests for native platforms are located in the `x_file_io_test.dart`. Tests can -be run with `dart test`. +See https://pub.dev/documentation/cross_file_android/latest/cross_file_android/cross_file_android-library.html +for more details on Android Scoped Storage features. -### Web tests +See https://pub.dev/documentation/cross_file_io/latest/cross_file_io/cross_file_io-library.html +for more details on `dart:io` features. -Tests for the web platform live in the `x_file_html_test.dart`. They can be run -with `dart test -p chrome`. +See https://pub.dev/documentation/cross_file_web/latest/cross_file_web/cross_file_web-library.html +for more details on Web features. diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 94e3c879b87c..319bc465ef53 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -2,9 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// ignore_for_file: avoid_print - import 'package:cross_file/cross_file.dart'; +import 'package:flutter/foundation.dart' show debugPrint; /// Demonstrate instantiating an XFile for the README. Future instantiateXFile() async { @@ -12,12 +11,13 @@ Future instantiateXFile() async { final file = XFile('assets/hello.txt'); print('File information:'); - print('- Path: ${file.path}'); - print('- Name: ${file.name}'); - print('- MIME type: ${file.mimeType}'); + print('- URI: ${file.uri}'); + print('- Name: ${await file.name()}'); - final String fileContent = await file.readAsString(); - print('Content of the file: $fileContent'); + if (await file.canRead()) { + final String fileContent = await file.readAsString(); + debugPrint('Content of the file: $fileContent'); + } // #enddocregion Instantiate return file; diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md index 315574218feb..b360059af5be 100644 --- a/packages/cross_file/cross_file_web/README.md +++ b/packages/cross_file/cross_file_web/README.md @@ -11,5 +11,26 @@ so you do not need to add it to your `pubspec.yaml`. However, if you `import` this package to use any of its APIs directly, you should add it to your `pubspec.yaml` as usual. +## Limitations + +`XFile` on the web platform is backed by [Blob](https://api.dart.dev/be/180361/dart-html/Blob-class.html) +objects and their URLs. + +It seems that Safari hangs when reading Blobs larger than 4GB (your app will stop without returning +any data, or throwing an exception). + +This package will attempt to throw an `Exception` before a large file is accessed from Safari (if +its size is known beforehand), so that case can be handled programmatically. + +### Browser compatibility + +[![Data on Global support for Blob constructing](https://caniuse.bitsofco.de/image/blobbuilder.png)](https://caniuse.com/blobbuilder) + +[![Data on Global support for Blob URLs](https://caniuse.bitsofco.de/image/bloburls.png)](https://caniuse.com/bloburls) + +### Tests + +Tests for the web platform can be run with `dart test -p chrome`. + [1]: https://pub.dev/packages/cross_file [2]: https://flutter.dev/to/endorsed-federated-plugin From 39d4bbc9ec3b5f2b87b6d2b46f34fdc244d76c68 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:13:18 -0700 Subject: [PATCH 113/398] default implementations for cross file implementations --- packages/cross_file/cross_file/dart_test.yaml | 6 -- .../example/test/readme_excerpts_test.dart | 23 ----- .../lib/src/cross_file_platform.dart | 83 ++++++++++++++++--- .../lib/src/platform_cross_directory.dart | 3 + 4 files changed, 75 insertions(+), 40 deletions(-) delete mode 100644 packages/cross_file/cross_file/dart_test.yaml delete mode 100644 packages/cross_file/cross_file/example/test/readme_excerpts_test.dart diff --git a/packages/cross_file/cross_file/dart_test.yaml b/packages/cross_file/cross_file/dart_test.yaml deleted file mode 100644 index cdb656dbb689..000000000000 --- a/packages/cross_file/cross_file/dart_test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments -override_platforms: - chrome: - settings: - executable: chrome - arguments: --no-sandbox diff --git a/packages/cross_file/cross_file/example/test/readme_excerpts_test.dart b/packages/cross_file/cross_file/example/test/readme_excerpts_test.dart deleted file mode 100644 index f46576cc0fdb..000000000000 --- a/packages/cross_file/cross_file/example/test/readme_excerpts_test.dart +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:cross_file/cross_file.dart'; -import 'package:cross_file_example/readme_excerpts.dart'; -import 'package:test/test.dart'; - -const bool kIsWeb = bool.fromEnvironment('dart.library.js_interop'); - -void main() { - test('instantiateXFile loads asset file', () async { - // Ensure that the snippet code runs successfully. - final XFile xFile = await instantiateXFile(); - // It should have a nonempty path and name. - expect(xFile.path, allOf(isNotNull, isNotEmpty)); - expect(xFile.name, allOf(isNotNull, isNotEmpty)); - - // And the example file should have contents. - final String fileContent = await xFile.readAsString(); - expect(fileContent, allOf(isNotNull, isNotEmpty)); - }, skip: kIsWeb); -} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index bfb4edabd0b5..bc97f9a9d336 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/foundation.dart'; +import 'dart:convert'; + +import 'dart:typed_data'; import 'platform_cross_directory.dart'; import 'platform_cross_file.dart'; +import 'platform_cross_file_entity.dart'; import 'scoped_storage/platform_scoped_storage_cross_directory.dart'; import 'scoped_storage/platform_scoped_storage_cross_file.dart'; @@ -21,30 +24,88 @@ abstract base class CrossFilePlatform { PlatformXFile createPlatformXFile(PlatformXFileCreationParams params); /// Creates a new [PlatformXDirectory]. - @optionalTypeArgs PlatformXDirectory createPlatformXDirectory( PlatformXDirectoryCreationParams params, ) { - throw UnimplementedError( - 'createPlatformXDirectory is not implemented on the current platform.', - ); + return _DefaultXDirectory(params); } /// Creates a new [PlatformScopedStorageXDirectory]. PlatformScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, ) { - throw UnimplementedError( - 'createPlatformScopedStorageXFile is not implemented on the current platform.', - ); + return _DefaultScopedStorageXFile(params); } /// Creates a new [PlatformScopedStorageXDirectory]. PlatformScopedStorageXDirectory createPlatformScopedStorageXDirectory( PlatformScopedStorageXDirectoryCreationParams params, ) { - throw UnimplementedError( - 'createPlatformScopedStorageXDirectory is not implemented on the current platform.', - ); + return _DefaultScopedStorageXDirectory(params); + } +} + +/// Implementation of [PlatformXDirectory} that represents a resource that does +/// not exist. +final class _DefaultXDirectory extends PlatformXDirectory { + _DefaultXDirectory(super.params) : super.implementation(); + + @override + Future exists() async => false; + + @override + Stream list(ListParams params) { + throw UnsupportedError('This instance does not represent any directory.'); + } +} + +/// Implementation of [PlatformXDirectory} that represents a resource that does +/// not exist. +final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { + _DefaultScopedStorageXFile(super.params) : super.implementation(); + + @override + Future canRead() async => false; + + @override + Future exists() async => false; + + @override + Future lastModified() async => null; + + @override + Future length() async => null; + + @override + Future name() async => null; + + @override + Stream openRead([int? start, int? end]) { + throw UnsupportedError('This instance does not represent any resource.'); + } + + @override + Future readAsBytes() { + throw UnsupportedError('This instance does not represent any resource.'); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + throw UnsupportedError('This instance does not represent any resource.'); + } +} + +/// Implementation of [PlatformXDirectory} that represents a resource that does +/// not exist. +final class _DefaultScopedStorageXDirectory + extends PlatformScopedStorageXDirectory { + _DefaultScopedStorageXDirectory(super.params) : super.implementation(); + + @override + Future exists() async => false; + + @override + Stream list(ListParams params) { + throw UnsupportedError('This instance does not represent any directory.'); } } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 1762cb46fc7e..6459e61e19f7 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -97,6 +97,9 @@ abstract base class PlatformXDirectory extends PlatformXFileEntity { super.params as PlatformXDirectoryCreationParams; /// Lists the sub-directories and files of this Directory. + /// + /// Platforms may throw an exception if there is an error listing entities in + /// the directory Stream list(ListParams params); } From fa7f420fe7414c57bff882dbe861ec8531197b73 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:17:36 -0700 Subject: [PATCH 114/398] add tests for default impl --- .../test/cross_file_platform_test.dart | 48 ++++++++++++++++--- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 30f925867fbb..f2151012e541 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -12,15 +12,51 @@ import 'package:flutter_test/flutter_test.dart'; void main() { group('CrossFilePlatform', () { test( - 'Default implementation of createPlatformXDirectory should throw unimplemented error', - () { + 'Default implementation of createPlatformXDirectory should return an implementation that returns false for exists()', + () async { final platform = TestCrossFilePlatform(); expect( - () => platform.createPlatformXDirectory( - const PlatformXDirectoryCreationParams(uri: 'test'), - ), - throwsUnimplementedError, + await platform + .createPlatformXDirectory( + const PlatformXDirectoryCreationParams(uri: 'test'), + ) + .exists(), + false, + ); + }, + ); + + test( + 'Default implementation of createPlatformScopedStorageXFile should return an implementation that returns false for exists()', + () async { + final platform = TestCrossFilePlatform(); + + expect( + await platform + .createPlatformScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: 'test'), + ) + .exists(), + false, + ); + }, + ); + + test( + 'Default implementation of createPlatformScopedStorageXDirectory should return an implementation that returns false for exists()', + () async { + final platform = TestCrossFilePlatform(); + + expect( + await platform + .createPlatformScopedStorageXDirectory( + const PlatformScopedStorageXDirectoryCreationParams( + uri: 'test', + ), + ) + .exists(), + false, ); }, ); From b88d1376fbeb44cd6870c86caec9ff8d80475dde Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:19:22 -0700 Subject: [PATCH 115/398] update docs --- .../lib/src/cross_file_platform.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index bc97f9a9d336..4ac3ad48cf2c 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -45,7 +45,7 @@ abstract base class CrossFilePlatform { } } -/// Implementation of [PlatformXDirectory} that represents a resource that does +/// Implementation of [PlatformXDirectory} that represents a directory that does /// not exist. final class _DefaultXDirectory extends PlatformXDirectory { _DefaultXDirectory(super.params) : super.implementation(); @@ -59,8 +59,8 @@ final class _DefaultXDirectory extends PlatformXDirectory { } } -/// Implementation of [PlatformXDirectory} that represents a resource that does -/// not exist. +/// Implementation of [PlatformScopedStorageXFile} that represents a resource +/// that does not exist. final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { _DefaultScopedStorageXFile(super.params) : super.implementation(); @@ -95,8 +95,8 @@ final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { } } -/// Implementation of [PlatformXDirectory} that represents a resource that does -/// not exist. +/// Implementation of [PlatformScopedStorageXDirectory} that represents a +/// directory that does not exist. final class _DefaultScopedStorageXDirectory extends PlatformScopedStorageXDirectory { _DefaultScopedStorageXDirectory(super.params) : super.implementation(); From e57c8bbd68e8cac05385ad80dd64c4cbe6f0c717 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:43:22 -0700 Subject: [PATCH 116/398] add base test files --- .../cross_file/test/assets/hello.txt | 1 - .../cross_file/test/cross_file_test.dart | 89 +++++++ .../cross_file/cross_file/test/test_file.txt | 1 + .../cross_file/test/test_stubs.dart | 228 ++++++++++++++++++ .../cross_file/test/x_file_html_test.dart | 171 ------------- .../cross_file/test/x_file_io_test.dart | 134 ---------- 6 files changed, 318 insertions(+), 306 deletions(-) delete mode 100644 packages/cross_file/cross_file/test/assets/hello.txt create mode 100644 packages/cross_file/cross_file/test/cross_file_test.dart create mode 100644 packages/cross_file/cross_file/test/test_file.txt create mode 100644 packages/cross_file/cross_file/test/test_stubs.dart delete mode 100644 packages/cross_file/cross_file/test/x_file_html_test.dart delete mode 100644 packages/cross_file/cross_file/test/x_file_io_test.dart diff --git a/packages/cross_file/cross_file/test/assets/hello.txt b/packages/cross_file/cross_file/test/assets/hello.txt deleted file mode 100644 index 5dd01c177f5d..000000000000 --- a/packages/cross_file/cross_file/test/assets/hello.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, world! \ No newline at end of file diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart new file mode 100644 index 000000000000..33087c169933 --- /dev/null +++ b/packages/cross_file/cross_file/test/cross_file_test.dart @@ -0,0 +1,89 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; + +final File testFile = File( + path.join(Directory.current.path, 'test', 'test_file.txt'), +); + +void main() { + group('IOXFile', () { + setUp(() { + CrossFilePlatform.instance = CrossFileIO(); + }); + + test('lastModified', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.lastModified(), testFile.lastModifiedSync()); + }); + + test('length', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.length(), await testFile.length()); + }); + + test('openRead', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect( + await file.openRead().toList(), + await testFile.openRead().toList(), + ); + }); + + test('readAsBytes', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.readAsBytes(), await testFile.readAsBytes()); + }); + + test('readAsString', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.readAsString(), await testFile.readAsString()); + }); + + test('canRead', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.canRead(), testFile.existsSync()); + }); + + test('exists', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.exists(), testFile.existsSync()); + }); + + test('name', () async { + final file = PlatformXFile( + PlatformXFileCreationParams(uri: testFile.path), + ); + + expect(await file.name(), 'test_file.txt'); + }); + }); +} diff --git a/packages/cross_file/cross_file/test/test_file.txt b/packages/cross_file/cross_file/test/test_file.txt new file mode 100644 index 000000000000..b45ef6fec895 --- /dev/null +++ b/packages/cross_file/cross_file/test/test_file.txt @@ -0,0 +1 @@ +Hello, World! \ No newline at end of file diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart new file mode 100644 index 000000000000..5902684d13f7 --- /dev/null +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -0,0 +1,228 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; + +import 'dart:typed_data'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + +final class TestCrossFilePlatform extends CrossFilePlatform { + TestCrossFilePlatform({this.onCreatePlatformXFile}); + + PlatformXFile Function(PlatformXFileCreationParams params)? + onCreatePlatformXFile; + + PlatformXDirectory Function(PlatformXDirectoryCreationParams params)? + onCreatePlatformXDirectory; + + PlatformScopedStorageXFile Function( + PlatformScopedStorageXFileCreationParams params, + )? + onCreatePlatformScopedStorageXFile; + + PlatformScopedStorageXDirectory Function( + PlatformScopedStorageXDirectoryCreationParams params, + )? + onCreatePlatformScopedStorageXDirectory; + + @override + PlatformXFile createPlatformXFile(PlatformXFileCreationParams params) { + return onCreatePlatformXFile?.call(params) ?? TestXFile(params); + } + + @override + PlatformXDirectory createPlatformXDirectory( + PlatformXDirectoryCreationParams params, + ) { + return onCreatePlatformXDirectory?.call(params) ?? TestXDirectory(params); + } + + @override + PlatformScopedStorageXFile createPlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, + ) { + return onCreatePlatformScopedStorageXFile?.call(params) ?? + TestScopedStorageXFile(params); + } + + @override + PlatformScopedStorageXDirectory createPlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams params, + ) { + return onCreatePlatformScopedStorageXDirectory?.call(params) ?? + TestScopedStorageXDirectory(params); + } +} + +final class TestXFile extends PlatformXFile { + TestXFile( + super.params, { + this.onCanRead, + this.onExists, + this.onLastModified, + this.onLength, + this.onName, + this.onOpenRead, + this.onReadAsBytes, + this.onReadAsString, + }) : super.implementation(); + + Future Function()? onCanRead; + Future Function()? onExists; + Future Function()? onLastModified; + Future Function()? onLength; + Future Function()? onName; + Stream Function()? onOpenRead; + Future Function()? onReadAsBytes; + Future Function({Encoding encoding})? onReadAsString; + + @override + Future canRead() async { + return await onCanRead?.call() ?? false; + } + + @override + Future exists() async { + return await onExists?.call() ?? false; + } + + @override + Future lastModified() async { + return await onLastModified?.call(); + } + + @override + Future length() async { + return await onLength?.call(); + } + + @override + Future name() async { + return await onName?.call(); + } + + @override + Stream openRead([int? start, int? end]) async* { + if (onOpenRead != null) { + yield* onOpenRead!.call(); + } + } + + @override + Future readAsBytes() async { + return await onReadAsBytes?.call() ?? Uint8List(0); + } + + @override + Future readAsString({Encoding encoding = utf8}) async { + return await onReadAsString?.call(encoding: encoding) ?? ''; + } +} + +final class TestXDirectory extends PlatformXDirectory { + TestXDirectory(super.params, {this.onExists, this.onList}) + : super.implementation(); + + Future Function()? onExists; + Stream Function(ListParams params)? onList; + + @override + Future exists() async { + return await onExists?.call() ?? false; + } + + @override + Stream list(ListParams params) async* { + if (onList != null) { + yield* onList!.call(params); + } + } +} + +final class TestScopedStorageXFile extends PlatformScopedStorageXFile { + TestScopedStorageXFile( + super.params, { + this.onCanRead, + this.onExists, + this.onLastModified, + this.onLength, + this.onName, + this.onOpenRead, + this.onReadAsBytes, + this.onReadAsString, + }) : super.implementation(); + + Future Function()? onCanRead; + Future Function()? onExists; + Future Function()? onLastModified; + Future Function()? onLength; + Future Function()? onName; + Stream Function()? onOpenRead; + Future Function()? onReadAsBytes; + Future Function({Encoding encoding})? onReadAsString; + + @override + Future canRead() async { + return await onCanRead?.call() ?? false; + } + + @override + Future exists() async { + return await onExists?.call() ?? false; + } + + @override + Future lastModified() async { + return await onLastModified?.call(); + } + + @override + Future length() async { + return await onLength?.call(); + } + + @override + Future name() async { + return await onName?.call(); + } + + @override + Stream openRead([int? start, int? end]) async* { + if (onOpenRead != null) { + yield* onOpenRead!.call(); + } + } + + @override + Future readAsBytes() async { + return await onReadAsBytes?.call() ?? Uint8List(0); + } + + @override + Future readAsString({Encoding encoding = utf8}) async { + return await onReadAsString?.call(encoding: encoding) ?? ''; + } +} + +final class TestScopedStorageXDirectory + extends PlatformScopedStorageXDirectory { + TestScopedStorageXDirectory(super.params, {this.onExists, this.onList}) + : super.implementation(); + + Future Function()? onExists; + Stream Function(ListParams params)? onList; + + @override + Future exists() async { + return await onExists?.call() ?? false; + } + + @override + Stream list(ListParams params) async* { + if (onList != null) { + yield* onList!.call(params); + } + } +} diff --git a/packages/cross_file/cross_file/test/x_file_html_test.dart b/packages/cross_file/cross_file/test/x_file_html_test.dart deleted file mode 100644 index 75bbcebc6aa4..000000000000 --- a/packages/cross_file/cross_file/test/x_file_html_test.dart +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@TestOn('chrome') // Uses web-only Flutter SDK -library; - -import 'dart:convert'; -import 'dart:js_interop'; -import 'dart:typed_data'; - -import 'package:cross_file/cross_file.dart'; -import 'package:test/test.dart'; -import 'package:web/web.dart' as html; - -const String expectedStringContents = 'Hello, world! I ❤ ñ! 空手'; -final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); -final html.File textFile = html.File( - [bytes.toJS].toJS, - 'hello.txt', -); -final String textFileUrl = - // TODO(kevmoo): drop ignore when pkg:web constraint excludes v0.3 - // ignore: unnecessary_cast - html.URL.createObjectURL(textFile as JSObject); - -void main() { - group('Create with an objectUrl', () { - final file = XFile(textFileUrl); - - test('Can be read as a string', () async { - expect(await file.readAsString(), equals(expectedStringContents)); - }); - - test('Can be read as bytes', () async { - expect(await file.readAsBytes(), equals(bytes)); - }); - - test('Can be read as a stream', () async { - expect(await file.openRead().first, equals(bytes)); - }); - - test('Stream can be sliced', () async { - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - }); - - group('Create from data', () { - final file = XFile.fromData(bytes); - - test('Can be read as a string', () async { - expect(await file.readAsString(), equals(expectedStringContents)); - }); - - test('Can be read as bytes', () async { - expect(await file.readAsBytes(), equals(bytes)); - }); - - test('Can be read as a stream', () async { - expect(await file.openRead().first, equals(bytes)); - }); - - test('Stream can be sliced', () async { - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - - test('Prefers local bytes over path if both are provided', () async { - const text = 'Hello World'; - const path = 'test/x_file_html_test.dart'; - - final file = XFile.fromData( - utf8.encode(text), - path: path, - name: 'x_file_html_test.dart', - length: text.length, - mimeType: 'text/plain', - lastModified: DateTime.now(), - ); - - expect(file.path, isNot(equals(path))); - expect(file.path.startsWith('blob:'), isTrue); - expect(await file.readAsString(), equals(text)); - }); - }); - - group('Blob backend', () { - final file = XFile(textFileUrl); - - test('Stores data as a Blob', () async { - // Read the blob from its path 'natively' - final html.Response response = await html.window - .fetch(file.path.toJS) - .toDart; - - final JSAny arrayBuffer = await response.arrayBuffer().toDart; - final ByteBuffer data = (arrayBuffer as JSArrayBuffer).toDart; - expect(data.asUint8List(), equals(bytes)); - }); - - test('Data may be purged from the blob!', () async { - html.URL.revokeObjectURL(file.path); - - expect(() async { - await file.readAsBytes(); - }, throwsException); - }); - }); - - group('saveTo(..)', () { - const crossFileDomElementId = '__x_file_dom_element'; - - group('CrossFile saveTo(..)', () { - test('creates a DOM container', () async { - final file = XFile.fromData(bytes); - - await file.saveTo(''); - - final html.Element? container = html.document.querySelector( - '#$crossFileDomElementId', - ); - - expect(container, isNotNull); - }); - - test('create anchor element', () async { - final file = XFile.fromData(bytes, name: textFile.name); - - await file.saveTo('path'); - - final html.Element container = html.document.querySelector( - '#$crossFileDomElementId', - )!; - - late html.HTMLAnchorElement element; - for (var i = 0; i < container.childNodes.length; i++) { - final html.Element test = container.children.item(i)!; - if (test.tagName == 'A') { - element = test as html.HTMLAnchorElement; - break; - } - } - - // if element is not found, the `firstWhere` call will throw StateError. - expect(element.href, file.path); - expect(element.download, file.name); - }); - - test('anchor element is clicked', () async { - final mockAnchor = - html.document.createElement('a') as html.HTMLAnchorElement; - - final overrides = CrossFileTestOverrides( - createAnchorElement: (_, __) => mockAnchor, - ); - - final file = XFile.fromData( - bytes, - name: textFile.name, - overrides: overrides, - ); - - var clicked = false; - mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); - - await file.saveTo('path'); - - expect(clicked, true); - }); - }); - }); -} diff --git a/packages/cross_file/cross_file/test/x_file_io_test.dart b/packages/cross_file/cross_file/test/x_file_io_test.dart deleted file mode 100644 index 904a5c08c507..000000000000 --- a/packages/cross_file/cross_file/test/x_file_io_test.dart +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@TestOn('vm') // Uses dart:io -library; - -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:cross_file/cross_file.dart'; -import 'package:test/test.dart'; - -final String pathPrefix = Directory.current.path.endsWith('test') - ? './assets/' - : './test/assets/'; -final String path = '${pathPrefix}hello.txt'; -const String expectedStringContents = 'Hello, world!'; -final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); -final File textFile = File(path); -final String textFilePath = textFile.path; - -void main() { - group('Create with a path', () { - test('Can be read as a string', () async { - final file = XFile(textFilePath); - expect(await file.readAsString(), equals(expectedStringContents)); - }); - test('Can be read as bytes', () async { - final file = XFile(textFilePath); - expect(await file.readAsBytes(), equals(bytes)); - }); - - test('Can be read as a stream', () async { - final file = XFile(textFilePath); - expect(await file.openRead().first, equals(bytes)); - }); - - test('Stream can be sliced', () async { - final file = XFile(textFilePath); - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - - test('saveTo(..) creates file', () async { - final file = XFile(textFilePath); - final Directory tempDir = Directory.systemTemp.createTempSync(); - final targetFile = File('${tempDir.path}/newFilePath.txt'); - if (targetFile.existsSync()) { - await targetFile.delete(); - } - - await file.saveTo(targetFile.path); - - expect(targetFile.existsSync(), isTrue); - expect(targetFile.readAsStringSync(), 'Hello, world!'); - - await tempDir.delete(recursive: true); - }); - - test('saveTo(..) does not load the file into memory', () async { - final file = TestXFile(textFilePath); - final Directory tempDir = Directory.systemTemp.createTempSync(); - final targetFile = File('${tempDir.path}/newFilePath.txt'); - if (targetFile.existsSync()) { - await targetFile.delete(); - } - - await file.saveTo(targetFile.path); - - expect(file.hasBeenRead, isFalse); - - await tempDir.delete(recursive: true); - }); - - test('nullability is correct', () async { - expect(_ensureNonnullPathArgument('a/path'), isNotNull); - }); - }); - - group('Create with data', () { - final file = XFile.fromData(bytes); - - test('Can be read as a string', () async { - expect(await file.readAsString(), equals(expectedStringContents)); - }); - test('Can be read as bytes', () async { - expect(await file.readAsBytes(), equals(bytes)); - }); - - test('Can be read as a stream', () async { - expect(await file.openRead().first, equals(bytes)); - }); - - test('Stream can be sliced', () async { - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - - test('Function saveTo(..) creates file', () async { - final Directory tempDir = Directory.systemTemp.createTempSync(); - final targetFile = File('${tempDir.path}/newFilePath.txt'); - if (targetFile.existsSync()) { - await targetFile.delete(); - } - - await file.saveTo(targetFile.path); - - expect(targetFile.existsSync(), isTrue); - expect(targetFile.readAsStringSync(), 'Hello, world!'); - - await tempDir.delete(recursive: true); - }); - }); -} - -// This is to create an analysis error if the version of XFile in -// interface.dart, which should never actually be used but is what the analyzer -// runs against, has the nullability of `path` changed. -XFile _ensureNonnullPathArgument(String? path) { - return XFile(path!); -} - -/// An XFile subclass that tracks reads, for testing purposes. -class TestXFile extends XFile { - TestXFile(super.path); - - bool hasBeenRead = false; - - @override - Future readAsBytes() { - hasBeenRead = true; - return super.readAsBytes(); - } -} From cf7239e8fee8e07d07d3352e1ec1b5efb96be069 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:53:14 -0700 Subject: [PATCH 117/398] fix platform implementations --- .../cross_file/example/pubspec.yaml | 2 +- .../cross_file/test/cross_file_test.dart | 139 +++++++++--------- .../cross_file/test/test_stubs.dart | 7 +- .../cross_file/cross_file_io/pubspec.yaml | 9 ++ .../cross_file/cross_file_web/pubspec.yaml | 1 - 5 files changed, 84 insertions(+), 74 deletions(-) diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index 6302aa15b8e9..26df1875431e 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - file_selector: ^1.1.0 + #file_selector: ^1.1.0 flutter: sdk: flutter flutter_driver: diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart index 33087c169933..da135b52d114 100644 --- a/packages/cross_file/cross_file/test/cross_file_test.dart +++ b/packages/cross_file/cross_file/test/cross_file_test.dart @@ -4,86 +4,83 @@ import 'dart:io'; -import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file/cross_file.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:path/path.dart' as path; -final File testFile = File( - path.join(Directory.current.path, 'test', 'test_file.txt'), -); +import 'test_stubs.dart'; void main() { - group('IOXFile', () { - setUp(() { - CrossFilePlatform.instance = CrossFileIO(); - }); - + group('XFile', () { test('lastModified', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect(await file.lastModified(), testFile.lastModifiedSync()); - }); - - test('length', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect(await file.length(), await testFile.length()); - }); - - test('openRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect( - await file.openRead().toList(), - await testFile.openRead().toList(), - ); - }); - - test('readAsBytes', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + final lastModified = DateTime.now(); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onLastModified: () async => lastModified), ); - expect(await file.readAsBytes(), await testFile.readAsBytes()); - }); - - test('readAsString', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect(await file.readAsString(), await testFile.readAsString()); - }); - - test('canRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect(await file.canRead(), testFile.existsSync()); - }); - - test('exists', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect(await file.exists(), testFile.existsSync()); - }); - - test('name', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = XFile('uri'); - expect(await file.name(), 'test_file.txt'); + expect(await file.lastModified(), lastModified); }); + // + // test('length', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect(await file.length(), await testFile.length()); + // }); + // + // test('openRead', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect( + // await file.openRead().toList(), + // await testFile.openRead().toList(), + // ); + // }); + // + // test('readAsBytes', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect(await file.readAsBytes(), await testFile.readAsBytes()); + // }); + // + // test('readAsString', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect(await file.readAsString(), await testFile.readAsString()); + // }); + // + // test('canRead', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect(await file.canRead(), testFile.existsSync()); + // }); + // + // test('exists', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect(await file.exists(), testFile.existsSync()); + // }); + // + // test('name', () async { + // final file = PlatformXFile( + // PlatformXFileCreationParams(uri: testFile.path), + // ); + // + // expect(await file.name(), 'test_file.txt'); + // }); }); } diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 5902684d13f7..8bfc1b99ac10 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -9,7 +9,12 @@ import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; final class TestCrossFilePlatform extends CrossFilePlatform { - TestCrossFilePlatform({this.onCreatePlatformXFile}); + TestCrossFilePlatform({ + this.onCreatePlatformXFile, + this.onCreatePlatformXDirectory, + this.onCreatePlatformScopedStorageXFile, + this.onCreatePlatformScopedStorageXDirectory, + }); PlatformXFile Function(PlatformXFileCreationParams params)? onCreatePlatformXFile; diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index f4718c7f75f7..af4afd3c78fd 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -8,6 +8,15 @@ environment: sdk: ^3.9.0 flutter: ">=3.35.0" +flutter: + plugin: + implements: cross_file + platforms: + linux: + dartPluginClass: CrossFileIO + windows: + dartPluginClass: CrossFileIO + dependencies: cross_file_platform_interface: path: ../cross_file_platform_interface diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 3c68441fcebb..a6ec6bbd0c87 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -14,7 +14,6 @@ flutter: platforms: web: pluginClass: CrossFileWeb - fileName: cross_file_web.dart dependencies: cross_file_platform_interface: From 420146680f6c16577fd0190a9b00e773b851296b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:37:13 -0500 Subject: [PATCH 118/398] directory tests --- .../cross_file/test/cross_directory_test.dart | 53 ++++++ .../cross_file/test/cross_file_test.dart | 151 +++++++++++------- .../cross_file/cross_file/test/test_file.txt | 1 - .../cross_file/test/test_stubs.dart | 13 +- 4 files changed, 156 insertions(+), 62 deletions(-) create mode 100644 packages/cross_file/cross_file/test/cross_directory_test.dart delete mode 100644 packages/cross_file/cross_file/test/test_file.txt diff --git a/packages/cross_file/cross_file/test/cross_directory_test.dart b/packages/cross_file/cross_file/test/cross_directory_test.dart new file mode 100644 index 000000000000..2a1bb5633bcc --- /dev/null +++ b/packages/cross_file/cross_file/test/cross_directory_test.dart @@ -0,0 +1,53 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file/cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'test_stubs.dart'; + +void main() { + group('XDirectory', () { + test('exists', () async { + const exists = true; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXDirectory: (PlatformXDirectoryCreationParams params) => + TestXDirectory(params, onExists: () async => exists), + ); + + final directory = XDirectory('uri'); + + expect(await directory.exists(), exists); + }); + + test('list', () async { + final entities = [ + TestXFile(const PlatformXFileCreationParams(uri: 'uri1')), + TestXDirectory(const PlatformXDirectoryCreationParams(uri: 'uri2')), + TestXFileEntity(const PlatformXFileCreationParams(uri: 'uri3')), + ]; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXDirectory: (PlatformXDirectoryCreationParams params) => + TestXDirectory( + params, + onList: (ListParams params) => Stream.fromIterable(entities), + ), + ); + + final directory = XDirectory('uri'); + + final List directoryEntities = await directory + .list() + .toList(); + expect(directoryEntities.length, entities.length); + expect(directoryEntities.first, isA()); + expect(directoryEntities.first.uri, entities.first.params.uri); + expect(directoryEntities[1], isA()); + expect(directoryEntities[1].uri, entities[1].params.uri); + expect(directoryEntities[2], isA()); + expect(directoryEntities[2].uri, entities[2].params.uri); + }); + }); +} diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart index da135b52d114..04788baf2b9a 100644 --- a/packages/cross_file/cross_file/test/cross_file_test.dart +++ b/packages/cross_file/cross_file/test/cross_file_test.dart @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:io'; +import 'dart:convert'; +import 'dart:typed_data'; import 'package:cross_file/cross_file.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -23,64 +24,94 @@ void main() { expect(await file.lastModified(), lastModified); }); - // - // test('length', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect(await file.length(), await testFile.length()); - // }); - // - // test('openRead', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect( - // await file.openRead().toList(), - // await testFile.openRead().toList(), - // ); - // }); - // - // test('readAsBytes', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect(await file.readAsBytes(), await testFile.readAsBytes()); - // }); - // - // test('readAsString', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect(await file.readAsString(), await testFile.readAsString()); - // }); - // - // test('canRead', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect(await file.canRead(), testFile.existsSync()); - // }); - // - // test('exists', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect(await file.exists(), testFile.existsSync()); - // }); - // - // test('name', () async { - // final file = PlatformXFile( - // PlatformXFileCreationParams(uri: testFile.path), - // ); - // - // expect(await file.name(), 'test_file.txt'); - // }); + + test('length', () async { + const length = 42; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onLength: () async => length), + ); + + final file = XFile('uri'); + + expect(await file.length(), length); + }); + + test('openRead', () async { + final data = [ + Uint8List.fromList([5, 6]), + ]; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onOpenRead: () => Stream.fromIterable(data)), + ); + + final file = XFile('uri'); + + expect(await file.openRead().toList(), data); + }); + + test('readAsBytes', () async { + final bytes = Uint8List.fromList([1, 2, 3]); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onReadAsBytes: () async => bytes), + ); + + final file = XFile('uri'); + + expect(await file.readAsBytes(), bytes); + }); + + test('readAsString', () async { + const message = 'Hello, World!'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile( + params, + onReadAsString: ({required Encoding encoding}) async => message, + ), + ); + + final file = XFile('uri'); + + expect(await file.readAsString(), message); + }); + + test('canRead', () async { + const canRead = false; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onCanRead: () async => canRead), + ); + + final file = XFile('uri'); + + expect(await file.canRead(), canRead); + }); + + test('exists', () async { + const exists = true; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onExists: () async => exists), + ); + + final file = XFile('uri'); + + expect(await file.exists(), exists); + }); + + test('name', () async { + const name = 'name'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformXFile: (PlatformXFileCreationParams params) => + TestXFile(params, onName: () async => name), + ); + + final file = XFile('uri'); + + expect(await file.name(), name); + }); }); } diff --git a/packages/cross_file/cross_file/test/test_file.txt b/packages/cross_file/cross_file/test/test_file.txt deleted file mode 100644 index b45ef6fec895..000000000000 --- a/packages/cross_file/cross_file/test/test_file.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, World! \ No newline at end of file diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 8bfc1b99ac10..350446d9505e 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -81,7 +81,7 @@ final class TestXFile extends PlatformXFile { Future Function()? onName; Stream Function()? onOpenRead; Future Function()? onReadAsBytes; - Future Function({Encoding encoding})? onReadAsString; + Future Function({required Encoding encoding})? onReadAsString; @override Future canRead() async { @@ -231,3 +231,14 @@ final class TestScopedStorageXDirectory } } } + +final class TestXFileEntity extends PlatformXFileEntity { + TestXFileEntity(super.params, {this.onExists}); + + Future Function()? onExists; + + @override + Future exists() async { + return await onExists?.call() ?? false; + } +} From 16c61f70641f89656997ba1bab769b8c4f7169ec Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:42:00 -0500 Subject: [PATCH 119/398] scoped storage tests --- .../scoped_storage_cross_directory_test.dart | 62 ++++++++ .../test/scoped_storage_cross_file_test.dart | 135 ++++++++++++++++++ .../cross_file/test/test_stubs.dart | 2 +- 3 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart create mode 100644 packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart new file mode 100644 index 000000000000..43e4be0af264 --- /dev/null +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -0,0 +1,62 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file/cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'test_stubs.dart'; + +void main() { + group('XDirectory', () { + test('exists', () async { + const exists = true; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXDirectory: + (PlatformScopedStorageXDirectoryCreationParams params) => + TestScopedStorageXDirectory( + params, + onExists: () async => exists, + ), + ); + + final directory = ScopedStorageXDirectory('uri'); + + expect(await directory.exists(), exists); + }); + + test('list', () async { + final entities = [ + TestScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: 'uri1'), + ), + TestScopedStorageXDirectory( + const PlatformScopedStorageXDirectoryCreationParams(uri: 'uri2'), + ), + TestXFileEntity(const PlatformXFileCreationParams(uri: 'uri3')), + ]; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXDirectory: + (PlatformScopedStorageXDirectoryCreationParams params) => + TestScopedStorageXDirectory( + params, + onList: (ListParams params) => Stream.fromIterable(entities), + ), + ); + + final directory = ScopedStorageXDirectory('uri'); + + final List directoryEntities = await directory + .list() + .toList(); + expect(directoryEntities.length, entities.length); + expect(directoryEntities.first, isA()); + expect(directoryEntities.first.uri, entities.first.params.uri); + expect(directoryEntities[1], isA()); + expect(directoryEntities[1].uri, entities[1].params.uri); + expect(directoryEntities[2], isA()); + expect(directoryEntities[2].uri, entities[2].params.uri); + }); + }); +} diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart new file mode 100644 index 000000000000..b15731d423df --- /dev/null +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart @@ -0,0 +1,135 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cross_file/cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'test_stubs.dart'; + +void main() { + group('XFile', () { + test('lastModified', () async { + final lastModified = DateTime.now(); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile( + params, + onLastModified: () async => lastModified, + ), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.lastModified(), lastModified); + }); + + test('length', () async { + const length = 42; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onLength: () async => length), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.length(), length); + }); + + test('openRead', () async { + final data = [ + Uint8List.fromList([5, 6]), + ]; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile( + params, + onOpenRead: () => Stream.fromIterable(data), + ), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.openRead().toList(), data); + }); + + test('readAsBytes', () async { + final bytes = Uint8List.fromList([1, 2, 3]); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile( + params, + onReadAsBytes: () async => bytes, + ), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.readAsBytes(), bytes); + }); + + test('readAsString', () async { + const message = 'Hello, World!'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile( + params, + onReadAsString: ({required Encoding encoding}) async => + message, + ), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.readAsString(), message); + }); + + test('canRead', () async { + const canRead = false; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onCanRead: () async => canRead), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.canRead(), canRead); + }); + + test('exists', () async { + const exists = true; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onExists: () async => exists), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.exists(), exists); + }); + + test('name', () async { + const name = 'name'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onName: () async => name), + ); + + final file = ScopedStorageXFile('uri'); + + expect(await file.name(), name); + }); + }); +} diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 350446d9505e..69337b87fb86 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -166,7 +166,7 @@ final class TestScopedStorageXFile extends PlatformScopedStorageXFile { Future Function()? onName; Stream Function()? onOpenRead; Future Function()? onReadAsBytes; - Future Function({Encoding encoding})? onReadAsString; + Future Function({required Encoding encoding})? onReadAsString; @override Future canRead() async { From da418ab4aabe9e7d3fb85951315ff5c19c337b79 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:31:23 -0500 Subject: [PATCH 120/398] update replace --- packages/cross_file/cross_file_web/lib/src/web_helpers.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index 3ed682282f43..5a31b62dee91 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -56,7 +56,10 @@ void downloadObjectUrl( : createAnchorElement(objectUrl, name); // Clear the children in target. - target.replaceChildren(JSArray()); + while (target.children.length > 0) { + target.removeChild(target.children.item(0)!); + } + // Add the new `element` and click. addElementToContainerAndClick(target, element); } From 55c6078378fcc9551a83edd42a9153150e4086df Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:35:03 -0500 Subject: [PATCH 121/398] remove unused path dep --- packages/cross_file/cross_file/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index 5ec397183790..2f873016f8dd 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -39,7 +39,6 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - path: ^1.8.1 topics: - files From 410451fa3c8a5c699c9894541f7ae64781c6521b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:52:41 -0500 Subject: [PATCH 122/398] flutter create init --- .../cross_file/cross_file/example/README.md | 9 + .../cross_file/example/android/.gitignore | 14 + .../example/android/app/build.gradle.kts | 44 ++ .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 45 ++ .../cross_file_example/MainActivity.kt | 5 + .../res/drawable-v21/launch_background.xml | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values-night/styles.xml | 18 + .../app/src/main/res/values/styles.xml | 18 + .../app/src/profile/AndroidManifest.xml | 7 + .../example/android/build.gradle.kts | 24 + .../example/android/gradle.properties | 2 + .../gradle/wrapper/gradle-wrapper.properties | 5 + .../example/android/settings.gradle.kts | 26 + .../cross_file/example/assets/hello.txt | 1 - .../cross_file/example/dart_test.yaml | 6 - .../ios/Flutter/AppFrameworkInfo.plist | 24 + .../example/ios/Flutter/Debug.xcconfig | 2 + .../example/ios/Flutter/Release.xcconfig | 2 + .../cross_file/cross_file/example/ios/Podfile | 43 ++ .../ios/Runner.xcodeproj/project.pbxproj | 623 ++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 101 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../example/ios/Runner/AppDelegate.swift | 16 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 295 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 450 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 282 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 462 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 704 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 406 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 862 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 1674 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 762 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 1226 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 1418 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/Runner/Base.lproj/Main.storyboard | 26 + .../cross_file/example/ios/Runner/Info.plist | 70 ++ .../ios/Runner/Runner-Bridging-Header.h | 1 + .../example/ios/Runner/SceneDelegate.swift | 6 + .../example/ios/RunnerTests/RunnerTests.swift | 12 + .../cross_file/example/linux/CMakeLists.txt | 128 ++++ .../example/linux/flutter/CMakeLists.txt | 88 +++ .../linux/flutter/generated_plugins.cmake | 23 + .../example/linux/runner/CMakeLists.txt | 26 + .../cross_file/example/linux/runner/main.cc | 6 + .../example/linux/runner/my_application.cc | 148 ++++ .../example/linux/runner/my_application.h | 21 + .../macos/Flutter/Flutter-Debug.xcconfig | 2 + .../macos/Flutter/Flutter-Release.xcconfig | 2 + .../cross_file/example/macos/Podfile | 42 ++ .../macos/Runner.xcodeproj/project.pbxproj | 705 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 99 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../example/macos/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2218 bytes .../macos/Runner/Base.lproj/MainMenu.xib | 343 +++++++++ .../macos/Runner/Configs/AppInfo.xcconfig | 14 + .../macos/Runner/Configs/Debug.xcconfig | 2 + .../macos/Runner/Configs/Release.xcconfig | 2 + .../macos/Runner/Configs/Warnings.xcconfig | 13 + .../macos/Runner/DebugProfile.entitlements | 12 + .../example/macos/Runner/Info.plist | 32 + .../macos/Runner/MainFlutterWindow.swift | 15 + .../example/macos/Runner/Release.entitlements | 8 + .../macos/RunnerTests/RunnerTests.swift | 12 + .../cross_file/example/web/favicon.png | Bin 0 -> 917 bytes .../cross_file/example/web/icons/Icon-192.png | Bin 0 -> 5292 bytes .../cross_file/example/web/icons/Icon-512.png | Bin 0 -> 8252 bytes .../example/web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes .../example/web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes .../cross_file/example/web/index.html | 46 ++ .../cross_file/example/web/manifest.json | 35 + .../cross_file/example/windows/CMakeLists.txt | 108 +++ .../example/windows/flutter/CMakeLists.txt | 109 +++ .../windows/flutter/generated_plugins.cmake | 23 + .../example/windows/runner/CMakeLists.txt | 40 + .../example/windows/runner/Runner.rc | 121 +++ .../example/windows/runner/flutter_window.cpp | 71 ++ .../example/windows/runner/flutter_window.h | 33 + .../example/windows/runner/main.cpp | 43 ++ .../example/windows/runner/resource.h | 16 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 14 + .../example/windows/runner/utils.cpp | 65 ++ .../cross_file/example/windows/runner/utils.h | 19 + .../example/windows/runner/win32_window.cpp | 288 +++++++ .../example/windows/runner/win32_window.h | 102 +++ 118 files changed, 4387 insertions(+), 7 deletions(-) create mode 100644 packages/cross_file/cross_file/example/README.md create mode 100644 packages/cross_file/cross_file/example/android/.gitignore create mode 100644 packages/cross_file/cross_file/example/android/app/build.gradle.kts create mode 100644 packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/values-night/styles.xml create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/res/values/styles.xml create mode 100644 packages/cross_file/cross_file/example/android/app/src/profile/AndroidManifest.xml create mode 100644 packages/cross_file/cross_file/example/android/build.gradle.kts create mode 100644 packages/cross_file/cross_file/example/android/gradle.properties create mode 100644 packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 packages/cross_file/cross_file/example/android/settings.gradle.kts delete mode 100644 packages/cross_file/cross_file/example/assets/hello.txt delete mode 100644 packages/cross_file/cross_file/example/dart_test.yaml create mode 100644 packages/cross_file/cross_file/example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 packages/cross_file/cross_file/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/cross_file/cross_file/example/ios/Flutter/Release.xcconfig create mode 100644 packages/cross_file/cross_file/example/ios/Podfile create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Info.plist create mode 100644 packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h create mode 100644 packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift create mode 100644 packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift create mode 100644 packages/cross_file/cross_file/example/linux/CMakeLists.txt create mode 100644 packages/cross_file/cross_file/example/linux/flutter/CMakeLists.txt create mode 100644 packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake create mode 100644 packages/cross_file/cross_file/example/linux/runner/CMakeLists.txt create mode 100644 packages/cross_file/cross_file/example/linux/runner/main.cc create mode 100644 packages/cross_file/cross_file/example/linux/runner/my_application.cc create mode 100644 packages/cross_file/cross_file/example/linux/runner/my_application.h create mode 100644 packages/cross_file/cross_file/example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 packages/cross_file/cross_file/example/macos/Flutter/Flutter-Release.xcconfig create mode 100644 packages/cross_file/cross_file/example/macos/Podfile create mode 100644 packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj create mode 100644 packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 packages/cross_file/cross_file/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Base.lproj/MainMenu.xib create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Configs/AppInfo.xcconfig create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Configs/Debug.xcconfig create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Configs/Release.xcconfig create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Configs/Warnings.xcconfig create mode 100644 packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Info.plist create mode 100644 packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift create mode 100644 packages/cross_file/cross_file/example/macos/Runner/Release.entitlements create mode 100644 packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift create mode 100644 packages/cross_file/cross_file/example/web/favicon.png create mode 100644 packages/cross_file/cross_file/example/web/icons/Icon-192.png create mode 100644 packages/cross_file/cross_file/example/web/icons/Icon-512.png create mode 100644 packages/cross_file/cross_file/example/web/icons/Icon-maskable-192.png create mode 100644 packages/cross_file/cross_file/example/web/icons/Icon-maskable-512.png create mode 100644 packages/cross_file/cross_file/example/web/index.html create mode 100644 packages/cross_file/cross_file/example/web/manifest.json create mode 100644 packages/cross_file/cross_file/example/windows/CMakeLists.txt create mode 100644 packages/cross_file/cross_file/example/windows/flutter/CMakeLists.txt create mode 100644 packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake create mode 100644 packages/cross_file/cross_file/example/windows/runner/CMakeLists.txt create mode 100644 packages/cross_file/cross_file/example/windows/runner/Runner.rc create mode 100644 packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp create mode 100644 packages/cross_file/cross_file/example/windows/runner/flutter_window.h create mode 100644 packages/cross_file/cross_file/example/windows/runner/main.cpp create mode 100644 packages/cross_file/cross_file/example/windows/runner/resource.h create mode 100644 packages/cross_file/cross_file/example/windows/runner/resources/app_icon.ico create mode 100644 packages/cross_file/cross_file/example/windows/runner/runner.exe.manifest create mode 100644 packages/cross_file/cross_file/example/windows/runner/utils.cpp create mode 100644 packages/cross_file/cross_file/example/windows/runner/utils.h create mode 100644 packages/cross_file/cross_file/example/windows/runner/win32_window.cpp create mode 100644 packages/cross_file/cross_file/example/windows/runner/win32_window.h diff --git a/packages/cross_file/cross_file/example/README.md b/packages/cross_file/cross_file/example/README.md new file mode 100644 index 000000000000..96b8bb17dbff --- /dev/null +++ b/packages/cross_file/cross_file/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/packages/cross_file/cross_file/example/android/.gitignore b/packages/cross_file/cross_file/example/android/.gitignore new file mode 100644 index 000000000000..be3943c96d8e --- /dev/null +++ b/packages/cross_file/cross_file/example/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle.kts b/packages/cross_file/cross_file/example/android/app/build.gradle.kts new file mode 100644 index 000000000000..adc6a98c5171 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "dev.flutter.packages.cross_file_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "dev.flutter.packages.cross_file_example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml b/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000000..399f6981d5d3 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/main/AndroidManifest.xml b/packages/cross_file/cross_file/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000000..5616b0f08984 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt new file mode 100644 index 000000000000..df679d6e1ecb --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt @@ -0,0 +1,5 @@ +package dev.flutter.packages.cross_file_example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/drawable-v21/launch_background.xml b/packages/cross_file/cross_file/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 000000000000..f74085f3f6a2 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/drawable/launch_background.xml b/packages/cross_file/cross_file/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 000000000000..304732f88420 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/packages/cross_file/cross_file/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/values-night/styles.xml b/packages/cross_file/cross_file/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 000000000000..06952be745f9 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/main/res/values/styles.xml b/packages/cross_file/cross_file/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000000..cb1ef88056ed --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/profile/AndroidManifest.xml b/packages/cross_file/cross_file/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 000000000000..399f6981d5d3 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/packages/cross_file/cross_file/example/android/build.gradle.kts b/packages/cross_file/cross_file/example/android/build.gradle.kts new file mode 100644 index 000000000000..dbee657bb5b9 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/packages/cross_file/cross_file/example/android/gradle.properties b/packages/cross_file/cross_file/example/android/gradle.properties new file mode 100644 index 000000000000..fbee1d8cdafc --- /dev/null +++ b/packages/cross_file/cross_file/example/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000000..e4ef43fb98df --- /dev/null +++ b/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/packages/cross_file/cross_file/example/android/settings.gradle.kts b/packages/cross_file/cross_file/example/android/settings.gradle.kts new file mode 100644 index 000000000000..ca7fe065c167 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +include(":app") diff --git a/packages/cross_file/cross_file/example/assets/hello.txt b/packages/cross_file/cross_file/example/assets/hello.txt deleted file mode 100644 index 5dd01c177f5d..000000000000 --- a/packages/cross_file/cross_file/example/assets/hello.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, world! \ No newline at end of file diff --git a/packages/cross_file/cross_file/example/dart_test.yaml b/packages/cross_file/cross_file/example/dart_test.yaml deleted file mode 100644 index cdb656dbb689..000000000000 --- a/packages/cross_file/cross_file/example/dart_test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments -override_platforms: - chrome: - settings: - executable: chrome - arguments: --no-sandbox diff --git a/packages/cross_file/cross_file/example/ios/Flutter/AppFrameworkInfo.plist b/packages/cross_file/cross_file/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 000000000000..391a902b2beb --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/packages/cross_file/cross_file/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..ec97fc6f3021 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..c4855bfe2000 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file/example/ios/Podfile b/packages/cross_file/cross_file/example/ios/Podfile new file mode 100644 index 000000000000..620e46eba607 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Podfile @@ -0,0 +1,43 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '13.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..ab8983ea48c7 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,623 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = PT2QK76LGP; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..919434a6254f --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..e3773d42e24c --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 000000000000..f9b0d7c5ea15 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift b/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift new file mode 100644 index 000000000000..c30b367ec0a9 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,16 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } +} diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..d36b1fab2d9d --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..797d452e458972bab9d994556c8305db4c827017 GIT binary patch literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..6ed2d933e1120817fe9182483a228007b18ab6ae GIT binary patch literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd7b0099ca80c806f8fe495613e8d6c69460d76 GIT binary patch literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fe730945a01f64a61e2235dbe3f45b08f7729182 GIT binary patch literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..502f463a9bc882b461c96aadf492d1729e49e725 GIT binary patch literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0ec303439225b78712f49115768196d8d76f6790 GIT binary patch literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..e9f5fea27c705180eb716271f41b582e76dcbd90 GIT binary patch literal 1674 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0467bf12aa4d28f374bb26596605a46dcbb3e7c8 GIT binary patch literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 000000000000..0bedcf2fd467 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 000000000000..89c2725b70f1 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/cross_file/cross_file/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/cross_file/cross_file/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 000000000000..f2e259c7c939 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner/Base.lproj/Main.storyboard b/packages/cross_file/cross_file/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 000000000000..f3c28516fb38 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner/Info.plist b/packages/cross_file/cross_file/example/ios/Runner/Info.plist new file mode 100644 index 000000000000..d512223bafe5 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Info.plist @@ -0,0 +1,70 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Cross File Example + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + cross_file_example + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h b/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 000000000000..308a2a560b42 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift b/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift new file mode 100644 index 000000000000..b9ce8ea2b2ad --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift @@ -0,0 +1,6 @@ +import Flutter +import UIKit + +class SceneDelegate: FlutterSceneDelegate { + +} diff --git a/packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..86a7c3b1b611 --- /dev/null +++ b/packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/packages/cross_file/cross_file/example/linux/CMakeLists.txt b/packages/cross_file/cross_file/example/linux/CMakeLists.txt new file mode 100644 index 000000000000..ed0f020b39f0 --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/CMakeLists.txt @@ -0,0 +1,128 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "cross_file_example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "dev.flutter.packages.cross_file_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/packages/cross_file/cross_file/example/linux/flutter/CMakeLists.txt b/packages/cross_file/cross_file/example/linux/flutter/CMakeLists.txt new file mode 100644 index 000000000000..d5bd01648a96 --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake b/packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000000..2e1de87a7eb6 --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/cross_file/cross_file/example/linux/runner/CMakeLists.txt b/packages/cross_file/cross_file/example/linux/runner/CMakeLists.txt new file mode 100644 index 000000000000..e97dabc7028e --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/packages/cross_file/cross_file/example/linux/runner/main.cc b/packages/cross_file/cross_file/example/linux/runner/main.cc new file mode 100644 index 000000000000..e7c5c5437037 --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/runner/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/packages/cross_file/cross_file/example/linux/runner/my_application.cc b/packages/cross_file/cross_file/example/linux/runner/my_application.cc new file mode 100644 index 000000000000..0c853ae28261 --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/runner/my_application.cc @@ -0,0 +1,148 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Called when first Flutter frame received. +static void first_frame_cb(MyApplication* self, FlView* view) { + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); +} + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "cross_file_example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "cross_file_example"); + } + + gtk_window_set_default_size(window, 1280, 720); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + GdkRGBA background_color; + // Background defaults to black, override it here if necessary, e.g. #00000000 + // for transparent. + gdk_rgba_parse(&background_color, "#000000"); + fl_view_set_background_color(view, &background_color); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + // Show the window when Flutter renders. + // Requires the view to be realized so we can start rendering. + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), + self); + gtk_widget_realize(GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); +} diff --git a/packages/cross_file/cross_file/example/linux/runner/my_application.h b/packages/cross_file/cross_file/example/linux/runner/my_application.h new file mode 100644 index 000000000000..db16367a77d0 --- /dev/null +++ b/packages/cross_file/cross_file/example/linux/runner/my_application.h @@ -0,0 +1,21 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, + my_application, + MY, + APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/packages/cross_file/cross_file/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cross_file/cross_file/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000000..4b81f9b2d200 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file/example/macos/Flutter/Flutter-Release.xcconfig b/packages/cross_file/cross_file/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000000..5caa9d1579e4 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file/example/macos/Podfile b/packages/cross_file/cross_file/example/macos/Podfile new file mode 100644 index 000000000000..ff5ddb3b8bdc --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Podfile @@ -0,0 +1,42 @@ +platform :osx, '10.15' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 000000000000..d338721e57bf --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* cross_file_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross_file_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* cross_file_example.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* cross_file_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_example"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_example"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_example"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 000000000000..cca2d5dd0577 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000000..1d526a16ed0f --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000000..18d981003d68 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift b/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift new file mode 100644 index 000000000000..b3c176141221 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000000..a2ec33f19f11 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..82b6f9d9a33e198f5747104729e1fcef999772a5 GIT binary patch literal 102994 zcmeEugo5nb1G~3xi~y`}h6XHx5j$(L*3|5S2UfkG$|UCNI>}4f?MfqZ+HW-sRW5RKHEm z^unW*Xx{AH_X3Xdvb%C(Bh6POqg==@d9j=5*}oEny_IS;M3==J`P0R!eD6s~N<36C z*%-OGYqd0AdWClO!Z!}Y1@@RkfeiQ$Ib_ z&fk%T;K9h`{`cX3Hu#?({4WgtmkR!u3ICS~|NqH^fdNz>51-9)OF{|bRLy*RBv#&1 z3Oi_gk=Y5;>`KbHf~w!`u}!&O%ou*Jzf|Sf?J&*f*K8cftMOKswn6|nb1*|!;qSrlw= zr-@X;zGRKs&T$y8ENnFU@_Z~puu(4~Ir)>rbYp{zxcF*!EPS6{(&J}qYpWeqrPWW< zfaApz%<-=KqxrqLLFeV3w0-a0rEaz9&vv^0ZfU%gt9xJ8?=byvNSb%3hF^X_n7`(fMA;C&~( zM$cQvQ|g9X)1AqFvbp^B{JEX$o;4iPi?+v(!wYrN{L}l%e#5y{j+1NMiT-8=2VrCP zmFX9=IZyAYA5c2!QO96Ea-6;v6*$#ZKM-`%JCJtrA3d~6h{u+5oaTaGE)q2b+HvdZ zvHlY&9H&QJ5|uG@wDt1h99>DdHy5hsx)bN`&G@BpxAHh$17yWDyw_jQhhjSqZ=e_k z_|r3=_|`q~uA47y;hv=6-o6z~)gO}ZM9AqDJsR$KCHKH;QIULT)(d;oKTSPDJ}Jx~G#w-(^r<{GcBC*~4bNjfwHBumoPbU}M)O za6Hc2ik)2w37Yyg!YiMq<>Aov?F2l}wTe+>h^YXcK=aesey^i)QC_p~S zp%-lS5%)I29WfywP(r4@UZ@XmTkqo51zV$|U|~Lcap##PBJ}w2b4*kt7x6`agP34^ z5fzu_8rrH+)2u*CPcr6I`gL^cI`R2WUkLDE5*PX)eJU@H3HL$~o_y8oMRoQ0WF9w| z6^HZDKKRDG2g;r8Z4bn+iJNFV(CG;K-j2>aj229gl_C6n12Jh$$h!}KVhn>*f>KcH z;^8s3t(ccVZ5<{>ZJK@Z`hn_jL{bP8Yn(XkwfRm?GlEHy=T($8Z1Mq**IM`zxN9>-yXTjfB18m_$E^JEaYn>pj`V?n#Xu;Z}#$- zw0Vw;T*&9TK$tKI7nBk9NkHzL++dZ^;<|F6KBYh2+XP-b;u`Wy{~79b%IBZa3h*3^ zF&BKfQ@Ej{7ku_#W#mNJEYYp=)bRMUXhLy2+SPMfGn;oBsiG_6KNL8{p1DjuB$UZB zA)a~BkL)7?LJXlCc}bB~j9>4s7tlnRHC5|wnycQPF_jLl!Avs2C3^lWOlHH&v`nGd zf&U!fn!JcZWha`Pl-B3XEe;(ks^`=Z5R zWyQR0u|do2`K3ec=YmWGt5Bwbu|uBW;6D8}J3{Uep7_>L6b4%(d=V4m#(I=gkn4HT zYni3cnn>@F@Wr<hFAY3Y~dW+3bte;70;G?kTn4Aw5nZ^s5|47 z4$rCHCW%9qa4)4vE%^QPMGf!ET!^LutY$G zqdT(ub5T5b+wi+OrV}z3msoy<4)`IPdHsHJggmog0K*pFYMhH!oZcgc5a)WmL?;TPSrerTVPp<#s+imF3v#!FuBNNa`#6 z!GdTCF|IIpz#(eV^mrYKThA4Bnv&vQet@%v9kuRu3EHx1-2-it@E`%9#u`)HRN#M? z7aJ{wzKczn#w^`OZ>Jb898^Xxq)0zd{3Tu7+{-sge-rQ z&0PME&wIo6W&@F|%Z8@@N3)@a_ntJ#+g{pUP7i?~3FirqU`rdf8joMG^ld?(9b7Iv z>TJgBg#)(FcW)h!_if#cWBh}f+V08GKyg|$P#KTS&%=!+0a%}O${0$i)kn9@G!}En zv)_>s?glPiLbbx)xk(lD-QbY(OP3;MSXM5E*P&_`Zks2@46n|-h$Y2L7B)iH{GAAq19h5-y0q>d^oy^y+soJu9lXxAe%jcm?=pDLFEG2kla40e!5a}mpe zdL=WlZ=@U6{>g%5a+y-lx)01V-x;wh%F{=qy#XFEAqcd+m}_!lQ)-9iiOL%&G??t| z?&NSdaLqdPdbQs%y0?uIIHY7rw1EDxtQ=DU!i{)Dkn~c$LG5{rAUYM1j5*G@oVn9~ zizz{XH(nbw%f|wI=4rw^6mNIahQpB)OQy10^}ACdLPFc2@ldVi|v@1nWLND?)53O5|fg`RZW&XpF&s3@c-R?aad!$WoH6u0B|}zt)L($E^@U- zO#^fxu9}Zw7Xl~nG1FVM6DZSR0*t!4IyUeTrnp@?)Z)*!fhd3)&s(O+3D^#m#bAem zpf#*aiG_0S^ofpm@9O7j`VfLU0+{$x!u^}3!zp=XST0N@DZTp!7LEVJgqB1g{psNr za0uVmh3_9qah14@M_pi~vAZ#jc*&aSm$hCNDsuQ-zPe&*Ii#2=2gP+DP4=DY z_Y0lUsyE6yaV9)K)!oI6+*4|spx2at*30CAx~6-5kfJzQ`fN8$!lz%hz^J6GY?mVH zbYR^JZ(Pmj6@vy-&!`$5soyy-NqB^8cCT40&R@|6s@m+ZxPs=Bu77-+Os7+bsz4nA3DrJ8#{f98ZMaj-+BD;M+Jk?pgFcZIb}m9N z{ct9T)Kye&2>l^39O4Q2@b%sY?u#&O9PO4@t0c$NUXG}(DZJ<;_oe2~e==3Z1+`Zo zFrS3ns-c}ZognVBHbg#e+1JhC(Yq7==rSJQ8J~}%94(O#_-zJKwnBXihl#hUd9B_>+T& z7eHHPRC?5ONaUiCF7w|{J`bCWS7Q&xw-Sa={j-f)n5+I=9s;E#fBQB$`DDh<^mGiF zu-m_k+)dkBvBO(VMe2O4r^sf3;sk9K!xgXJU>|t9Vm8Ty;fl5pZzw z9j|}ZD}6}t;20^qrS?YVPuPRS<39d^y0#O1o_1P{tN0?OX!lc-ICcHI@2#$cY}_CY zev|xdFcRTQ_H)1fJ7S0*SpPs8e{d+9lR~IZ^~dKx!oxz?=Dp!fD`H=LH{EeC8C&z-zK$e=!5z8NL=4zx2{hl<5z*hEmO=b-7(k5H`bA~5gT30Sjy`@-_C zKM}^so9Ti1B;DovHByJkTK87cfbF16sk-G>`Q4-txyMkyQS$d}??|Aytz^;0GxvOs zPgH>h>K+`!HABVT{sYgzy3CF5ftv6hI-NRfgu613d|d1cg^jh+SK7WHWaDX~hlIJ3 z>%WxKT0|Db1N-a4r1oPKtF--^YbP=8Nw5CNt_ZnR{N(PXI>Cm$eqi@_IRmJ9#)~ZHK_UQ8mi}w^`+4$OihUGVz!kW^qxnCFo)-RIDbA&k-Y=+*xYv5y4^VQ9S)4W5Pe?_RjAX6lS6Nz#!Hry=+PKx2|o_H_3M`}Dq{Bl_PbP(qel~P@=m}VGW*pK96 zI@fVag{DZHi}>3}<(Hv<7cVfWiaVLWr@WWxk5}GDEbB<+Aj;(c>;p1qmyAIj+R!`@#jf$ zy4`q23L-72Zs4j?W+9lQD;CYIULt%;O3jPWg2a%Zs!5OW>5h1y{Qof!p&QxNt5=T( zd5fy&7=hyq;J8%86YBOdc$BbIFxJx>dUyTh`L z-oKa=OhRK9UPVRWS`o2x53bAv+py)o)kNL6 z9W1Dlk-g6Ht@-Z^#6%`9S9`909^EMj?9R^4IxssCY-hYzei^TLq7Cj>z$AJyaU5=z zl!xiWvz0U8kY$etrcp8mL;sYqGZD!Hs-U2N{A|^oEKA482v1T%cs%G@X9M?%lX)p$ zZoC7iYTPe8yxY0Jne|s)fCRe1mU=Vb1J_&WcIyP|x4$;VSVNC`M+e#oOA`#h>pyU6 z?7FeVpk`Hsu`~T3i<_4<5fu?RkhM;@LjKo6nX>pa%8dSdgPO9~Jze;5r>Tb1Xqh5q z&SEdTXevV@PT~!O6z|oypTk7Qq+BNF5IQ(8s18c=^0@sc8Gi|3e>VKCsaZ?6=rrck zl@oF5Bd0zH?@15PxSJIRroK4Wa?1o;An;p0#%ZJ^tI=(>AJ2OY0GP$E_3(+Zz4$AQ zW)QWl<4toIJ5TeF&gNXs>_rl}glkeG#GYbHHOv-G!%dJNoIKxn)FK$5&2Zv*AFic! z@2?sY&I*PSfZ8bU#c9fdIJQa_cQijnj39-+hS@+~e*5W3bj%A}%p9N@>*tCGOk+cF zlcSzI6j%Q|2e>QG3A<86w?cx6sBtLNWF6_YR?~C)IC6_10SNoZUHrCpp6f^*+*b8` zlx4ToZZuI0XW1W)24)92S)y0QZa);^NRTX6@gh8@P?^=#2dV9s4)Q@K+gnc{6|C}& zDLHr7nDOLrsH)L@Zy{C_2UrYdZ4V{|{c8&dRG;wY`u>w%$*p>PO_}3`Y21pk?8Wtq zGwIXTulf7AO2FkPyyh2TZXM1DJv>hI`}x`OzQI*MBc#=}jaua&czSkI2!s^rOci|V zFkp*Vbiz5vWa9HPFXMi=BV&n3?1?%8#1jq?p^3wAL`jgcF)7F4l<(H^!i=l-(OTDE zxf2p71^WRIExLf?ig0FRO$h~aA23s#L zuZPLkm>mDwBeIu*C7@n@_$oSDmdWY7*wI%aL73t~`Yu7YwE-hxAATmOi0dmB9|D5a zLsR7OQcA0`vN9m0L|5?qZ|jU+cx3_-K2!K$zDbJ$UinQy<9nd5ImWW5n^&=Gg>Gsh zY0u?m1e^c~Ug39M{{5q2L~ROq#c{eG8Oy#5h_q=#AJj2Yops|1C^nv0D1=fBOdfAG z%>=vl*+_w`&M7{qE#$xJJp_t>bSh7Mpc(RAvli9kk3{KgG5K@a-Ue{IbU{`umXrR3ra5Y7xiX42+Q%N&-0#`ae_ z#$Y6Wa++OPEDw@96Zz##PFo9sADepQe|hUy!Zzc2C(L`k9&=a8XFr+!hIS>D2{pdGP1SzwyaGLiH3j--P>U#TWw90t8{8Bt%m7Upspl#=*hS zhy|(XL6HOqBW}Og^tLX7 z+`b^L{O&oqjwbxDDTg2B;Yh2(fW>%S5Pg8^u1p*EFb z`(fbUM0`afawYt%VBfD&b3MNJ39~Ldc@SAuzsMiN%E}5{uUUBc7hc1IUE~t-Y9h@e7PC|sv$xGx=hZiMXNJxz5V(np%6u{n24iWX#!8t#>Ob$in<>dw96H)oGdTHnU zSM+BPss*5)Wz@+FkooMxxXZP1{2Nz7a6BB~-A_(c&OiM)UUNoa@J8FGxtr$)`9;|O z(Q?lq1Q+!E`}d?KemgC!{nB1JJ!B>6J@XGQp9NeQvtbM2n7F%v|IS=XWPVZY(>oq$ zf=}8O_x`KOxZoGnp=y24x}k6?gl_0dTF!M!T`={`Ii{GnT1jrG9gPh)R=RZG8lIR| z{ZJ6`x8n|y+lZuy${fuEDTAf`OP!tGySLXD}ATJO5UoZv|Xo3%7O~L63+kw}v)Ci=&tWx3bQJfL@5O18CbPlkR^IcKA zy1=^Vl-K-QBP?9^R`@;czcUw;Enbbyk@vJQB>BZ4?;DM%BUf^eZE+sOy>a){qCY6Y znYy;KGpch-zf=5|p#SoAV+ie8M5(Xg-{FoLx-wZC9IutT!(9rJ8}=!$!h%!J+vE2e z(sURwqCC35v?1>C1L)swfA^sr16{yj7-zbT6Rf26-JoEt%U?+|rQ zeBuGohE?@*!zR9)1P|3>KmJSgK*fOt>N>j}LJB`>o(G#Dduvx7@DY7};W7K;Yj|8O zGF<+gTuoIKe7Rf+LQG3-V1L^|E;F*}bQ-{kuHq}| ze_NwA7~US19sAZ)@a`g*zkl*ykv2v3tPrb4Og2#?k6Lc7@1I~+ew48N&03hW^1Cx+ zfk5Lr4-n=#HYg<7ka5i>2A@ZeJ60gl)IDX!!p zzfXZQ?GrT>JEKl7$SH!otzK6=0dIlqN)c23YLB&Krf9v-{@V8p+-e2`ujFR!^M%*; ze_7(Jh$QgoqwB!HbX=S+^wqO15O_TQ0-qX8f-|&SOuo3ZE{{9Jw5{}>MhY}|GBhO& zv48s_B=9aYQfa;d>~1Z$y^oUUaDer>7ve5+Gf?rIG4GZ!hRKERlRNgg_C{W_!3tsI2TWbX8f~MY)1Q`6Wj&JJ~*;ay_0@e zzx+mE-pu8{cEcVfBqsnm=jFU?H}xj@%CAx#NO>3 z_re3Rq%d1Y7VkKy{=S73&p;4^Praw6Y59VCP6M?!Kt7{v#DG#tz?E)`K95gH_mEvb z%$<~_mQ$ad?~&T=O0i0?`YSp?E3Dj?V>n+uTRHAXn`l!pH9Mr}^D1d@mkf+;(tV45 zH_yfs^kOGLXlN*0GU;O&{=awxd?&`{JPRr$z<1HcAO2K`K}92$wC}ky&>;L?#!(`w z68avZGvb728!vgw>;8Z8I@mLtI`?^u6R>sK4E7%=y)jpmE$fH!Dj*~(dy~-2A5Cm{ zl{1AZw`jaDmfvaB?jvKwz!GC}@-Dz|bFm1OaPw(ia#?>vF7Y5oh{NVbyD~cHB1KFn z9C@f~X*Wk3>sQH9#D~rLPslAd26@AzMh=_NkH_yTNXx6-AdbAb z{Ul89YPHslD?xAGzOlQ*aMYUl6#efCT~WI zOvyiewT=~l1W(_2cEd(8rDywOwjM-7P9!8GCL-1<9KXXO=6%!9=W++*l1L~gRSxLVd8K=A7&t52ql=J&BMQu{fa6y zXO_e>d?4X)xp2V8e3xIQGbq@+vo#&n>-_WreTTW0Yr?|YRPP43cDYACMQ(3t6(?_k zfgDOAU^-pew_f5U#WxRXB30wcfDS3;k~t@b@w^GG&<5n$Ku?tT(%bQH(@UHQGN)N|nfC~7?(etU`}XB)$>KY;s=bYGY#kD%i9fz= z2nN9l?UPMKYwn9bX*^xX8Y@%LNPFU>s#Ea1DaP%bSioqRWi9JS28suTdJycYQ+tW7 zrQ@@=13`HS*dVKaVgcem-45+buD{B;mUbY$YYULhxK)T{S?EB<8^YTP$}DA{(&)@S zS#<8S96y9K2!lG^VW-+CkfXJIH;Vo6wh)N}!08bM$I7KEW{F6tqEQ?H@(U zAqfi%KCe}2NUXALo;UN&k$rU0BLNC$24T_mcNY(a@lxR`kqNQ0z%8m>`&1ro40HX} z{{3YQ;2F9JnVTvDY<4)x+88i@MtXE6TBd7POk&QfKU-F&*C`isS(T_Q@}K)=zW#K@ zbXpcAkTT-T5k}Wj$dMZl7=GvlcCMt}U`#Oon1QdPq%>9J$rKTY8#OmlnNWBYwafhx zqFnym@okL#Xw>4SeRFejBnZzY$jbO)e^&&sHBgMP%Ygfi!9_3hp17=AwLBNFTimf0 zw6BHNXw19Jg_Ud6`5n#gMpqe%9!QB^_7wAYv8nrW94A{*t8XZu0UT&`ZHfkd(F{Px zD&NbRJP#RX<=+sEeGs2`9_*J2OlECpR;4uJie-d__m*(aaGE}HIo+3P{my@;a~9Y$ zHBXVJ83#&@o6{M+pE9^lI<4meLLFN_3rwgR4IRyp)~OF0n+#ORrcJ2_On9-78bWbG zuCO0esc*n1X3@p1?lN{qWS?l7J$^jbpeel{w~51*0CM+q9@9X=>%MF(ce~om(}?td zjkUmdUR@LOn-~6LX#=@a%rvj&>DFEoQscOvvC@&ZB5jVZ-;XzAshwx$;Qf@U41W=q zOSSjQGQV8Qi3*4DngNMIM&Cxm7z*-K`~Bl(TcEUxjQ1c=?)?wF8W1g;bAR%sM#LK( z_Op?=P%)Z+J!>vpN`By0$?B~Out%P}kCriDq@}In&fa_ZyKV+nLM0E?hfxuu%ciUz z>yAk}OydbWNl7{)#112j&qmw;*Uj&B;>|;Qwfc?5wIYIHH}s6Mve@5c5r+y)jK9i( z_}@uC(98g)==AGkVN?4>o@w=7x9qhW^ zB(b5%%4cHSV?3M?k&^py)j*LK16T^Ef4tb05-h-tyrjt$5!oo4spEfXFK7r_Gfv7#x$bsR7T zs;dqxzUg9v&GjsQGKTP*=B(;)be2aN+6>IUz+Hhw-n>^|`^xu*xvjGPaDoFh2W4-n z@Wji{5Y$m>@Vt7TE_QVQN4*vcfWv5VY-dT0SV=l=8LAEq1go*f zkjukaDV=3kMAX6GAf0QOQHwP^{Z^=#Lc)sh`QB)Ftl&31jABvq?8!3bt7#8vxB z53M{4{GR4Hl~;W3r}PgXSNOt477cO62Yj(HcK&30zsmWpvAplCtpp&mC{`2Ue*Bwu zF&UX1;w%`Bs1u%RtGPFl=&sHu@Q1nT`z={;5^c^^S~^?2-?<|F9RT*KQmfgF!7=wD@hytxbD;=9L6PZrK*1<4HMObNWehA62DtTy)q5H|57 z9dePuC!1;0MMRRl!S@VJ8qG=v^~aEU+}2Qx``h1LII!y{crP2ky*R;Cb;g|r<#ryo zju#s4dE?5CTIZKc*O4^3qWflsQ(voX>(*_JP7>Q&$%zCAIBTtKC^JUi@&l6u&t0hXMXjz_y!;r@?k|OU9aD%938^TZ>V? zqJmom_6dz4DBb4Cgs_Ef@}F%+cRCR%UMa9pi<-KHN;t#O@cA%(LO1Rb=h?5jiTs93 zPLR78p+3t>z4|j=<>2i4b`ketv}9Ax#B0)hn7@bFl;rDfP8p7u9XcEb!5*PLKB(s7wQC2kzI^@ae)|DhNDmSy1bOLid%iIap@24A(q2XI!z_hkl-$1T10 z+KKugG4-}@u8(P^S3PW4x>an;XWEF-R^gB{`t8EiP{ZtAzoZ!JRuMRS__-Gg#Qa3{<;l__CgsF+nfmFNi}p z>rV!Y6B@cC>1up)KvaEQiAvQF!D>GCb+WZsGHjDeWFz?WVAHP65aIA8u6j6H35XNYlyy8>;cWe3ekr};b;$9)0G`zsc9LNsQ&D?hvuHRpBxH)r-1t9|Stc*u<}Ol&2N+wPMom}d15_TA=Aprp zjN-X3*Af$7cDWMWp##kOH|t;c2Pa9Ml4-)o~+7P;&q8teF-l}(Jt zTGKOQqJTeT!L4d}Qw~O0aanA$Vn9Rocp-MO4l*HK)t%hcp@3k0%&_*wwpKD6ThM)R z8k}&7?)YS1ZYKMiy?mn>VXiuzX7$Ixf7EW8+C4K^)m&eLYl%#T=MC;YPvD&w#$MMf zQ=>`@rh&&r!@X&v%ZlLF42L_c=5dSU^uymKVB>5O?AouR3vGv@ei%Z|GX5v1GK2R* zi!!}?+-8>J$JH^fPu@)E6(}9$d&9-j51T^n-e0Ze%Q^)lxuex$IL^XJ&K2oi`wG}QVGk2a7vC4X?+o^z zsCK*7`EUfSuQA*K@Plsi;)2GrayQOG9OYF82Hc@6aNN5ulqs1Of-(iZQdBI^U5of^ zZg2g=Xtad7$hfYu6l~KDQ}EU;oIj(3nO#u9PDz=eO3(iax7OCmgT2p_7&^3q zg7aQ;Vpng*)kb6=sd5?%j5Dm|HczSChMo8HHq_L8R;BR5<~DVyU$8*Tk5}g0eW5x7 z%d)JFZ{(Y<#OTKLBA1fwLM*fH7Q~7Sc2Ne;mVWqt-*o<;| z^1@vo_KTYaMnO$7fbLL+qh#R$9bvnpJ$RAqG+z8h|} z3F5iwG*(sCn9Qbyg@t0&G}3fE0jGq3J!JmG2K&$urx^$z95) z7h?;4vE4W=v)uZ*Eg3M^6f~|0&T)2D;f+L_?M*21-I1pnK(pT$5l#QNlT`SidYw~o z{`)G)Asv#cue)Ax1RNWiRUQ(tQ(bzd-f2U4xlJK+)ZWBxdq#fp=A>+Qc%-tl(c)`t z$e2Ng;Rjvnbu7((;v4LF9Y1?0el9hi!g>G{^37{ z`^s-03Z5jlnD%#Mix19zkU_OS|86^_x4<0(*YbPN}mi-$L?Z4K(M|2&VV*n*ZYN_UqI?eKZi3!b)i z%n3dzUPMc-dc|q}TzvPy!VqsEWCZL(-eURDRG4+;Eu!LugSSI4Fq$Ji$Dp08`pfP_C5Yx~`YKcywlMG;$F z)R5!kVml_Wv6MSpeXjG#g?kJ0t_MEgbXlUN3k|JJ%N>|2xn8yN>>4qxh!?dGI}s|Y zDTKd^JCrRSN+%w%D_uf=Tj6wIV$c*g8D96jb^Kc#>5Fe-XxKC@!pIJw0^zu;`_yeb zhUEm-G*C=F+jW%cP(**b61fTmPn2WllBr4SWNdKe*P8VabZsh0-R|?DO=0x`4_QY) zR7sthW^*BofW7{Sak&S1JdiG?e=SfL24Y#w_)xrBVhGB-13q$>mFU|wd9Xqe-o3{6 zSn@@1@&^)M$rxb>UmFuC+pkio#T;mSnroMVZJ%nZ!uImi?%KsIX#@JU2VY(`kGb1A z7+1MEG)wd@)m^R|a2rXeviv$!emwcY(O|M*xV!9%tBzarBOG<4%gI9SW;Um_gth4=gznYzOFd)y8e+3APCkL)i-OI`;@7-mCJgE`js(M} z;~ZcW{{FMVVO)W>VZ}ILouF#lWGb%Couu}TI4kubUUclW@jEn6B_^v!Ym*(T*4HF9 zWhNKi8%sS~viSdBtnrq!-Dc5(G^XmR>DFx8jhWvR%*8!m*b*R8e1+`7{%FACAK`7 zzdy8TmBh?FVZ0vtw6npnWwM~XjF2fNvV#ZlGG z?FxHkXHN>JqrBYoPo$)zNC7|XrQfcqmEXWud~{j?La6@kbHG@W{xsa~l1=%eLly8B z4gCIH05&Y;6O2uFSopNqP|<$ml$N40^ikxw0`o<~ywS1(qKqQN!@?Ykl|bE4M?P+e zo$^Vs_+x)iuw?^>>`$&lOQOUkZ5>+OLnRA)FqgpDjW&q*WAe(_mAT6IKS9;iZBl8M z<@=Y%zcQUaSBdrs27bVK`c$)h6A1GYPS$y(FLRD5Yl8E3j0KyH08#8qLrsc_qlws; znMV%Zq8k+&T2kf%6ZO^2=AE9>?a587g%-={X}IS~P*I(NeCF9_9&`)|ok0iiIun zo+^odT0&Z4k;rn7I1v87=z!zKU(%gfB$(1mrRYeO$sbqM22Kq68z9wgdg8HBxp>_< zn9o%`f?sVO=IN#5jSX&CGODWlZfQ9A)njK2O{JutYwRZ?n0G_p&*uwpE`Md$iQxrd zoQfF^b8Ou)+3BO_3_K5y*~?<(BF@1l+@?Z6;^;U>qlB)cdro;rxOS1M{Az$s^9o5sXDCg8yD<=(pKI*0e zLk>@lo#&s0)^*Q+G)g}C0IErqfa9VbL*Qe=OT@&+N8m|GJF7jd83vY#SsuEv2s{Q> z>IpoubNs>D_5?|kXGAPgF@mb_9<%hjU;S0C8idI)a=F#lPLuQJ^7OnjJlH_Sks9JD zMl1td%YsWq3YWhc;E$H1<0P$YbSTqs`JKY%(}svsifz|h8BHguL82dBl+z0^YvWk8 zGy;7Z0v5_FJ2A$P0wIr)lD?cPR%cz>kde!=W%Ta^ih+Dh4UKdf7ip?rBz@%y2&>`6 zM#q{JXvW9ZlaSk1oD!n}kSmcDa2v6T^Y-dy+#fW^y>eS8_%<7tWXUp8U@s$^{JFfKMjDAvR z$YmVB;n3ofl!ro9RNT!TpQpcycXCR}$9k5>IPWDXEenQ58os?_weccrT+Bh5sLoiH zZ_7~%t(vT)ZTEO= zb0}@KaD{&IyK_sd8b$`Qz3%UA`nSo zn``!BdCeN!#^G;lK@G2ron*0jQhbdw)%m$2;}le@z~PSLnU-z@tL)^(p%P>OO^*Ff zNRR9oQ`W+x^+EU+3BpluwK77|B3=8QyT|$V;02bn_LF&3LhLA<#}{{)jE)}CiW%VEU~9)SW+=F%7U-iYlQ&q!#N zwI2{(h|Pi&<8_fqvT*}FLN^0CxN}#|3I9G_xmVg$gbn2ZdhbmGk7Q5Q2Tm*ox8NMo zv`iaZW|ZEOMyQga5fts?&T-eCCC9pS0mj7v0SDkD=*^MxurP@89v&Z#3q{FM!a_nr zb?KzMv`BBFOew>4!ft@A&(v-kWXny-j#egKef|#!+3>26Qq0 zv!~8ev4G`7Qk>V1TaMT-&ziqoY3IJp8_S*%^1j73D|=9&;tDZH^!LYFMmME4*Wj(S zRt~Q{aLb_O;wi4u&=}OYuj}Lw*j$@z*3>4&W{)O-oi@9NqdoU!=U%d|se&h?^$Ip# z)BY+(1+cwJz!yy4%l(aLC;T!~Ci>yAtXJb~b*yr&v7f{YCU8P|N1v~H`xmGsG)g)y z4%mv=cPd`s7a*#OR7f0lpD$ueP>w8qXj0J&*7xX+U!uat5QNk>zwU$0acn5p=$88L=jn_QCSYkTV;1~(yUem#0gB`FeqY98sf=>^@ z_MCdvylv~WL%y_%y_FE1)j;{Szj1+K7Lr_y=V+U zk6Tr;>XEqlEom~QGL!a+wOf(@ZWoxE<$^qHYl*H1a~kk^BLPn785%nQb$o;Cuz0h& za9LMx^bKEbPS%e8NM33Jr|1T|ELC(iE!FUci38xW_Y7kdHid#2ie+XZhP;2!Z;ZAM zB_cXKm)VrPK!SK|PY00Phwrpd+x0_Aa;}cDQvWKrwnQrqz##_gvHX2ja?#_{f#;bz`i>C^^ zTLDy;6@HZ~XQi7rph!mz9k!m;KchA)uMd`RK4WLK7)5Rl48m#l>b(#`WPsl<0j z-sFkSF6>Nk|LKnHtZ`W_NnxZP62&w)S(aBmmjMDKzF%G;3Y?FUbo?>b5;0j8Lhtc4 zr*8d5Y9>g@FFZaViw7c16VsHcy0u7M%6>cG1=s=Dtx?xMJSKIu9b6GU8$uSzf43Y3 zYq|U+IWfH;SM~*N1v`KJo!|yfLxTFS?oHsr3qvzeVndVV^%BWmW6re_S!2;g<|Oao z+N`m#*i!)R%i1~NO-xo{qpwL0ZrL7hli;S z3L0lQ_z}z`fdK39Mg~Zd*%mBdD;&5EXa~@H(!###L`ycr7gW`f)KRuqyHL3|uyy3h zSS^td#E&Knc$?dXs*{EnPYOp^-vjAc-h4z#XkbG&REC7;0>z^^Z}i8MxGKerEY z>l?(wReOlXEsNE5!DO&ZWyxY)gG#FSZs%fXuzA~XIAPVp-%yb2XLSV{1nH6{)5opg z(dZKckn}Q4Li-e=eUDs1Psg~5zdn1>ql(*(nn6)iD*OcVkwmKL(A{fix(JhcVB&}V zVt*Xb!{gzvV}dc446>(D=SzfCu7KB`oMjv6kPzSv&B>>HLSJP|wN`H;>oRw*tl#N) z*zZ-xwM7D*AIsBfgqOjY1Mp9aq$kRa^dZU_xw~KxP;|q(m+@e+YSn~`wEJzM|Ippb zzb@%;hB7iH4op9SqmX?j!KP2chsb79(mFossBO-Zj8~L}9L%R%Bw<`^X>hjkCY5SG z7lY!8I2mB#z)1o;*3U$G)3o0A&{0}#B;(zPd2`OF`Gt~8;0Re8nIseU z_yzlf$l+*-wT~_-cYk$^wTJ@~7i@u(CZs9FVkJCru<*yK8&>g+t*!JqCN6RH%8S-P zxH8+Cy#W?!;r?cLMC(^BtAt#xPNnwboI*xWw#T|IW^@3|q&QYY6Ehxoh@^URylR|T zne-Y6ugE^7p5bkRDWIh)?JH5V^ub82l-LuVjDr7UT^g`q4dB&mBFRWGL_C?hoeL(% zo}ocH5t7|1Mda}T!^{Qt9vmA2ep4)dQSZO>?Eq8}qRp&ZJ?-`Tnw+MG(eDswP(L*X3ahC2Ad0_wD^ff9hfzb%Jd`IXx5 zae@NMzBXJDwJS?7_%!TB^E$N8pvhOHDK$7YiOelTY`6KX8hK6YyT$tk*adwN>s^Kp zwM3wGVPhwKU*Yq-*BCs}l`l#Tej(NQ>jg*S0TN%D+GcF<14Ms6J`*yMY;W<-mMN&-K>((+P}+t+#0KPGrzjP zJ~)=Bcz%-K!L5ozIWqO(LM)l_9lVOc4*S65&DKM#TqsiWNG{(EZQw!bc>qLW`=>p-gVJ;T~aN2D_- z{>SZC=_F+%hNmH6ub%Ykih0&YWB!%sd%W5 zHC2%QMP~xJgt4>%bU>%6&uaDtSD?;Usm}ari0^fcMhi_)JZgb1g5j zFl4`FQ*%ROfYI}e7RIq^&^a>jZF23{WB`T>+VIxj%~A-|m=J7Va9FxXV^%UwccSZd zuWINc-g|d6G5;95*%{e;9S(=%yngpfy+7ao|M7S|Jb0-4+^_q-uIqVS&ufU880UDH*>(c)#lt2j zzvIEN>>$Y(PeALC-D?5JfH_j+O-KWGR)TKunsRYKLgk7eu4C{iF^hqSz-bx5^{z0h ze2+u>Iq0J4?)jIo)}V!!m)%)B;a;UfoJ>VRQ*22+ncpe9f4L``?v9PH&;5j{WF?S_C>Lq>nkChZB zjF8(*v0c(lU^ZI-)_uGZnnVRosrO4`YinzI-RSS-YwjYh3M`ch#(QMNw*)~Et7Qpy z{d<3$4FUAKILq9cCZpjvKG#yD%-juhMj>7xIO&;c>_7qJ%Ae8Z^m)g!taK#YOW3B0 zKKSMOd?~G4h}lrZbtPk)n*iOC1~mDhASGZ@N{G|dF|Q^@1ljhe=>;wusA&NvY*w%~ zl+R6B^1yZiF)YN>0ms%}qz-^U-HVyiN3R9k1q4)XgDj#qY4CE0)52%evvrrOc898^ z*^)XFR?W%g0@?|6Mxo1ZBp%(XNv_RD-<#b^?-Fs+NL^EUW=iV|+Vy*F%;rBz~pN7%-698U-VMfGEVnmEz7fL1p)-5sLT zL;Iz>FCLM$p$c}g^tbkGK1G$IALq1Gd|We@&TtW!?4C7x4l*=4oF&&sr0Hu`x<5!m zhX&&Iyjr?AkNXU_5P_b^Q3U9sy#f6ZF@2C96$>1k*E-E%DjwvA{VL0PdU~suN~DZo zm{T!>sRdp`Ldpp9olrH@(J$QyGq!?#o1bUo=XP2OEuT3`XzI>s^0P{manUaE4pI%! zclQq;lbT;nx7v3tR9U)G39h?ryrxzd0xq4KX7nO?piJZbzT_CU&O=T(Vt;>jm?MgC z2vUL#*`UcMsx%w#vvjdamHhmN!(y-hr~byCA-*iCD};#l+bq;gkwQ0oN=AyOf@8ow>Pj<*A~2*dyjK}eYdN);%!t1 z6Y=|cuEv-|5BhA?n2Db@4s%y~(%Wse4&JXw=HiO48%c6LB~Z0SL1(k^9y?ax%oj~l zf7(`iAYLdPRq*ztFC z7VtAb@s{as%&Y;&WnyYl+6Wm$ru*u!MKIg_@01od-iQft0rMjIj8e7P9eKvFnx_X5 zd%pDg-|8<>T2Jdqw>AII+fe?CgP+fL(m0&U??QL8YzSjV{SFi^vW~;wN@or_(q<0Y zRt~L}#JRcHOvm$CB)T1;;7U>m%)QYBLTR)KTARw%zoDxgssu5#v{UEVIa<>{8dtkm zXgbCGp$tfue+}#SD-PgiNT{Zu^YA9;4BnM(wZ9-biRo_7pN}=aaimjYgC=;9@g%6< zxol5sT_$<8{LiJ6{l1+sV)Z_QdbsfEAEMw!5*zz6)Yop?T0DMtR_~wfta)E6_G@k# zZRP11D}$ir<`IQ`<(kGfAS?O-DzCyuzBq6dxGTNNTK?r^?zT30mLY!kQ=o~Hv*k^w zvq!LBjW=zzIi%UF@?!g9vt1CqdwV(-2LYy2=E@Z?B}JDyVkluHtzGsWuI1W5svX~K z&?UJ45$R7g>&}SFnLnmw09R2tUgmr_w6mM9C}8GvQX>nL&5R#xBqnp~Se(I>R42`T zqZe9p6G(VzNB3QD><8+y%{e%6)sZDRXTR|MI zM#eZmao-~_`N|>Yf;a;7yvd_auTG#B?Vz5D1AHx=zpVUFe7*hME z+>KH5h1In8hsVhrstc>y0Q!FHR)hzgl+*Q&5hU9BVJlNGRkXiS&06eOBV^dz3;4d5 zeYX%$62dNOprZV$px~#h1RH?_E%oD6y;J;pF%~y8M)8pQ0olYKj6 zE+hd|7oY3ot=j9ZZ))^CCPADL6Jw%)F@A{*coMApcA$7fZ{T@3;WOQ352F~q6`Mgi z$RI6$8)a`Aaxy<8Bc;{wlDA%*%(msBh*xy$L-cBJvQ8hj#FCyT^%+Phw1~PaqyDou^JR0rxDkSrmAdjeYDFDZ`E z)G3>XtpaSPDlydd$RGHg;#4|4{aP5c_Om z2u5xgnhnA)K%8iU==}AxPxZCYC)lyOlj9as#`5hZ=<6<&DB%i_XCnt5=pjh?iusH$ z>)E`@HNZcAG&RW3Ys@`Ci{;8PNzE-ZsPw$~Wa!cP$ye+X6;9ceE}ah+3VY7Mx}#0x zbqYa}eO*FceiY2jNS&2cH9Y}(;U<^^cWC5Ob&)dZedvZA9HewU3R;gRQ)}hUdf+~Q zS_^4ds*W1T#bxS?%RH&<739q*n<6o|mV;*|1s>ly-Biu<2*{!!0#{_234&9byvn0* z5=>{95Zfb{(?h_Jk#ocR$FZ78O*UTOxld~0UF!kyGM|nH%B*qf)Jy}N!uT9NGeM19 z-@=&Y0yGGo_dw!FD>juk%P$6$qJkj}TwLBoefi;N-$9LAeV|)|-ET&culW9Sb_pc_ zp{cXI0>I0Jm_i$nSvGnYeLSSj{ccVS2wyL&0x~&5v;3Itc82 z5lIAkfn~wcY-bQB$G!ufWt%qO;P%&2B_R5UKwYxMemIaFm)qF1rA zc>gEihb=jBtsXCi0T%J37s&kt*3$s7|6)L(%UiY)6axuk{6RWIS8^+u;)6!R?Sgap z9|6<0bx~AgVi|*;zL@2x>Pbt2Bz*uv4x-`{F)XatTs`S>unZ#P^ZiyjpfL_q2z^fqgR-fbOcG=Y$q>ozkw1T6dH8-)&ww+z?E0 zR|rV(9bi6zpX3Ub>PrPK!{X>e$C66qCXAeFm)Y+lX8n2Olt7PNs*1^si)j!QmFV#t z0P2fyf$N^!dyTot&`Ew5{i5u<8D`8U`qs(KqaWq5iOF3x2!-z65-|HsyYz(MAKZ?< zCpQR;E)wn%s|&q(LVm0Ab>gdmCFJeKwVTnv@Js%!At;I=A>h=l=p^&<4;Boc{$@h< z38v`3&2wJtka@M}GS%9!+SpJ}sdtoYzMevVbnH+d_eMxN@~~ zZq@k)7V5f8u!yAX2qF3qjS7g%n$JuGrMhQF!&S^7(%Y{rP*w2FWj(v_J{+Hg*}wdWOd~pHQ19&n3RWeljK9W%sz&Y3Tm3 zR`>6YR54%qBHGa)2xbs`9cs_EsNHxsfraEgZ)?vrtooeA0sPKJK7an){ngtV@{SBa zkO6ORr1_Xqp+`a0e}sC*_y(|RKS13ikmHp3C^XkE@&wjbGWrt^INg^9lDz#B;bHiW zkK4{|cg08b!yHFSgPca5)vF&gqCgeu+c82%&FeM^Bb}GUxLy-zo)}N;#U?sJ2?G2BNe*9u_7kE5JeY!it=f`A_4gV3} z`M!HXZy#gN-wS!HvHRqpCHUmjiM;rVvpkC!voImG%OFVN3k(QG@X%e``VJSJ@Z7tb z*Onlf>z^D+&$0!4`IE$;2-NSO9HQWd+UFW(r;4hh;(j^p4H-~6OE!HQp^96v?{9Zt z;@!ZcccV%C2s6FMP#qvo4kG6C04A>XILt>JW}%0oE&HM5f6 zYLD!;My>CW+j<~=Wzev{aYtx2ZNw|ptTFV(4;9`6Tmbz6K1)fv4qPXa2mtoPt&c?P zhmO+*o8uP3ykL6E$il00@TDf6tOW7fmo?Oz_6GU^+5J=c22bWyuH#aNj!tT-^IHrJ zu{aqTYw@q;&$xDE*_kl50Jb*dp`(-^p={z}`rqECTi~3 z>0~A7L6X)=L5p#~$V}gxazgGT7$3`?a)zen>?TvAuQ+KAIAJ-s_v}O6@`h9n-sZk> z`3{IJeb2qu9w=P*@q>iC`5wea`KxCxrx{>(4{5P+!cPg|pn~;n@DiZ0Y>;k5mnKeS z!LIfT4{Lgd=MeysR5YiQKCeNhUQ;Os1kAymg6R!u?j%LF z4orCszIq_n52ulpes{(QN|zirdtBsc{9^Z72Ycb2ht?G^opkT_#|4$wa9`)8k3ilU z%ntAi`nakS1r10;#k^{-ZGOD&Z2|k=p40hRh5D7(&JG#Cty|ECOvwsSHkkSa)36$4 z?;v#%@D(=Raw(HP5s>#4Bm?f~n1@ebH}2tv#7-0l-i^H#H{PC|F@xeNS+Yw{F-&wH z07)bj8MaE6`|6NoqKM~`4%X> zKFl&7g1$Z3HB>lxn$J`P`6GSb6CE6_^NA1V%=*`5O!zP$a7Vq)IwJAki~XBLf=4TF zPYSL}>4nOGZ`fyHChq)jy-f{PKFp6$plHB2=;|>%Z^%)ecVue(*mf>EH_uO^+_zm? zJATFa9SF~tFwR#&0xO{LLf~@}s_xvCPU8TwIJgBs%FFzjm`u?1699RTui;O$rrR{# z1^MqMl5&6)G%@_k*$U5Kxq84!AdtbZ!@8FslBML}<`(Jr zenXrC6bFJP=R^FMBg7P?Pww-!a%G@kJH_zezKvuWU0>m1uyy}#Vf<$>u?Vzo3}@O% z1JR`B?~Tx2)Oa|{DQ_)y9=oY%haj!80GNHw3~qazgU-{|q+Bl~H94J!a%8UR?XsZ@ z0*ZyQugyru`V9b(0OrJOKISfi89bSVR zQy<+i_1XY}4>|D%X_`IKZUPz6=TDb)t1mC9eg(Z=tv zq@|r37AQM6A%H%GaH3szv1L^ku~H%5_V*fv$UvHl*yN4iaqWa69T2G8J2f3kxc7UE zOia@p0YNu_q-IbT%RwOi*|V|&)e5B-u>4=&n@`|WzH}BK4?33IPpXJg%`b=dr_`hU z8JibW_3&#uIN_#D&hX<)x(__jUT&lIH$!txEC@cXv$7yB&Rgu){M`9a`*PH} zRcU)pMWI2O?x;?hzR{WdzKt^;_pVGJAKKd)F$h;q=Vw$MP1XSd<;Mu;EU5ffyKIg+ z&n-Nb?h-ERN7(fix`htopPIba?0Gd^y(4EHvfF_KU<4RpN0PgVxt%7Yo99X*Pe|zR z?ytK&5qaZ$0KSS$3ZNS$$k}y(2(rCl=cuYZg{9L?KVgs~{?5adxS))Upm?LDo||`H zV)$`FF3icFmxcQshXX*1k*w3O+NjBR-AuE70=UYM*7>t|I-oix=bzDwp2*RoIwBp@r&vZukG; zyi-2zdyWJ3+E?{%?>e2Ivk`fAn&Ho(KhGSVE4C-zxM-!j01b~mTr>J|5={PrZHOgO zw@ND3=z(J7D>&C7aw{zT>GHhL2BmUX0GLt^=31RRPSnjoUO9LYzh_yegyPoAKhAQE z>#~O27dR4&LdQiak6={9_{LN}Z>;kyVYKH^d^*!`JVSXJlx#&r4>VnP$zb{XoTb=> zZsLvh>keP3fkLTIDdpf-@(ADfq4=@X=&n>dyU0%dwD{zsjCWc;r`-e~X$Q3NTz_TJ zOXG|LMQQIjGXY3o5tBm9>k6y<6XNO<=9H@IXF;63rzsC=-VuS*$E{|L_i;lZmHOD< zY92;>4spdeRn4L6pY4oUKZG<~+8U-q7ZvNOtW0i*6Q?H`9#U3M*k#4J;ek(MwF02x zUo1wgq9o6XG#W^mxl>pAD)Ll-V5BNsdVQ&+QS0+K+?H-gIBJ-ccB1=M_hxB6qcf`C zJ?!q!J4`kLhAMry4&a_0}up{CFevcjBl|N(uDM^N5#@&-nQt2>z*U}eJGi}m5f}l|IRVj-Q;a>wcLpK5RRWJ> zysdd$)Nv0tS?b~bw1=gvz3L_ZAIdDDPj)y|bp1;LE`!av!rODs-tlc}J#?erTgXRX z$@ph%*~_wr^bQYHM7<7=Q=45v|Hk7T=mDpW@OwRy3A_v`ou@JX5h!VI*e((v*5Aq3 zVYfB4<&^Dq5%^?~)NcojqK`(VXP$`#w+&VhQOn%;4pCkz;NEH6-FPHTQ+7I&JE1+Ozq-g43AEZV>ceQ^9PCx zZG@OlEF~!Lq@5dttlr%+gNjRyMwJdJU(6W_KpuVnd{3Yle(-p#6erIRc${l&qx$HA z89&sp=rT7MJ=DuTL1<5{)wtUfpPA|Gr6Q2T*=%2RFm@jyo@`@^*{5{lFPgv>84|pv z%y{|cVNz&`9C*cUely>-PRL)lHVErAKPO!NQ3<&l5(>Vp(MuJnrOf^4qpIa!o3D7( z1bjn#Vv$#or|s7Hct5D@%;@48mM%ISY7>7@ft8f?q~{s)@BqGiupoK1BAg?PyaDQ1 z`YT8{0Vz{zBwJ={I4)#ny{RP{K1dqzAaQN_aaFC%Z>OZ|^VhhautjDavGtsQwx@WH zr|1UKk^+X~S*RjCY_HN!=Jx>b6J8`Q(l4y|mc<6jnkHVng^Wk(A13-;AhawATsmmE#H%|8h}f1frs2x@Fwa_|ea+$tdG2Pz{7 z!ox^w^>^Cv4e{Xo7EQ7bxCe8U+LZG<_e$RnR?p3t?s^1Mb!ieB z#@45r*PTc_yjh#P=O8Zogo+>1#|a2nJvhOjIqKK1U&6P)O%5s~M;99O<|Y9zomWTL z666lK^QW`)cXV_^Y05yQZH3IRCW%25BHAM$c0>w`x!jh^15Zp6xYb!LoQ zr+RukTw0X2mxN%K0%=8|JHiaA3pg5+GMfze%9o5^#upx0M?G9$+P^DTx7~qq9$Qoi zV$o)yy zuUq>3c{_q+HA5OhdN*@*RkxRuD>Bi{Ttv_hyaaB;XhB%mJ2Cb{yL;{Zu@l{N?!GKE7es6_9J{9 zO(tmc0ra2;@oC%SS-8|D=omQ$-Dj>S)Utkthh{ovD3I%k}HoranSepC_yco2Q8 zY{tAuPIhD{X`KbhQIr%!t+GeH%L%q&p z3P%<-S0YY2Emjc~Gb?!su85}h_qdu5XN2XJUM}X1k^!GbwuUPT(b$Ez#LkG6KEWQB z7R&IF4srHe$g2R-SB;inW9T{@+W+~wi7VQd?}7||zi!&V^~o0kM^aby7YE_-B63^d zf_uo8#&C77HBautt_YH%v6!Q>H?}(0@4pv>cM6_7dHJ)5JdyV0Phi!)vz}dv{*n;t zf(+#Hdr=f8DbJqbMez)(n>@QT+amJ7g&w6vZ-vG^H1v~aZqG~u!1D(O+jVAG0EQ*aIsr*bsBdbD`)i^FNJ z&B@yxqPFCRGT#}@dmu-{0vp47xk(`xNM6E=7QZ5{tg6}#zFrd8Pb_bFg7XP{FsYP8 zbvWqG6#jfg*4gvY9!gJxJ3l2UjP}+#QMB(*(?Y&Q4PO`EknE&Cb~Yb@lCbk;-KY)n zzbjS~W5KZ3FV%y>S#$9Sqi$FIBCw`GfPDP|G=|y32VV-g@a1D&@%_oAbB@cAUx#aZ zlAPTJ{iz#Qda8(aNZE&0q+8r3&z_Ln)b=5a%U|OEcc3h1f&8?{b8ErEbilrun}mh3 z$1o^$-XzIiH|iGoJA`w`o|?w3m*NX|sd$`Mt+f*!hyJvQ2fS*&!SYn^On-M|pHGlu z4SC5bM7f6BAkUhGuN*w`97LLkbCx=p@K5RL2p>YpDtf{WTD|d3ucb6iVZ-*DRtoEA zCC5(x)&e=giR_id>5bE^l%Mxx>0@FskpCD4oq@%-Fg$8IcdRwkfn;DsjoX(v;mt3d z_4Mnf#Ft4x!bY!7Hz?RRMq9;5FzugD(sbt4up~6j?-or+ch~y_PqrM2hhTToJjR_~ z)E1idgt7EW>G*9%Q^K;o_#uFjX!V2pwfpgi>}J&p_^QlZki!@#dkvR`p?bckC`J*g z=%3PkFT3HAX2Q+dShHUbb1?ZcK8U7oaufLTCB#1W{=~k0Jabgv>q|H+GU=f-y|{p4 zwN|AE+YbCgx=7vlXE?@gkXW9PaqbO#GB=4$o0FkNT#EI?aLVd2(qnPK$Yh%YD%v(mdwn}bgsxyIBI^)tY?&G zi^2JfClZ@4b{xFjyTY?D61w@*ez2@5rWLpG#34id?>>oPg{`4F-l`7Lg@D@Hc}On} zx%BO4MsLYosLGACJ-d?ifZ35r^t*}wde>AAWO*J-X%jvD+gL9`u`r=kP zyeJ%FqqKfz8e_3K(M1RmB?gIYi{W7Z<THP2ihue0mbpu5n(x_l|e1tw(q!#m5lmef6ktqIb${ zV+ee#XRU}_dDDUiV@opHZ@EbQ<9qIZJMDsZDkW0^t3#j`S)G#>N^ZBs8k+FJhAfu< z%u!$%dyP3*_+jUvCf-%{x#MyDAK?#iPfE<(@Q0H7;a125eD%I(+!x1f;Sy`e<9>nm zQH4czZDQmW7^n>jL)@P@aAuAF$;I7JZE5a8~AJI5CNDqyf$gjloKR7C?OPt9yeH}n5 zNF8Vhmd%1O>T4EZD&0%Dt7YWNImmEV{7QF(dy!>q5k>Kh&Xy8hcBMUvVV~Xn8O&%{ z&q=JCYw#KlwM8%cu-rNadu(P~i3bM<_a{3!J*;vZhR6dln6#eW0^0kN)Vv3!bqM`w z{@j*eyzz=743dgFPY`Cx3|>ata;;_hQ3RJd+kU}~p~aphRx`03B>g4*~f%hUV+#D9rYRbsGD?jkB^$3XcgB|3N1L& zrmk9&Dg450mAd=Q_p?gIy5Zx7vRL?*rpNq76_rysFo)z)tp0B;7lSb9G5wX1vC9Lc z5Q8tb-alolVNWFsxO_=12o}X(>@Mwz1mkYh1##(qQwN=7VKz?61kay8A9(94Ky(4V zq6qd2+4a20Z0QRrmp6C?4;%U?@MatfXnkj&U6bP_&2Ny}BF%4{QhNx*Tabik9Y-~Z z@0WV6XD}aI(%pN}oW$X~Qo_R#+1$@J8(31?zM`#e`#(0f<-AZ^={^NgH#lc?oi(Mu zMk|#KR^Q;V@?&(sh5)D;-fu)rx%gXZ1&5)MR+Mhssy+W>V%S|PRNyTAd}74<(#J>H zR(1BfM%eIv0+ngHH6(i`?-%_4!6PpK*0X)79SX0X$`lv_q>9(E2kkkP;?c@rW2E^Q zs<;`9dg|lDMNECFrD3jTM^Mn-C$44}9d9Kc z#>*k&e#25;D^%82^1d@Yt{Y91MbEu0C}-;HR4+IaCeZ`l?)Q8M2~&E^FvJ?EBJJ(% zz1>tCW-E~FB}DI}z#+fUo+=kQME^=eH>^%V8w)dh*ugPFdhMUi3R2Cg}Zak4!k_8YW(JcR-)hY8C zXja}R7@%Q0&IzQTk@M|)2ViZDNCDRLNI)*lH%SDa^2TG4;%jE4n`8`aQAA$0SPH2@ z)2eWZuP26+uGq+m8F0fZn)X^|bNe z#f{qYZS!(CdBdM$N2(JH_a^b#R2=>yVf%JI_ieRFB{w&|o9txwMrVxv+n78*aXFGb z>Rkj2yq-ED<)A46T9CL^$iPynv`FoEhUM10@J+UZ@+*@_gyboQ>HY9CiwTUo7OM=w zd~$N)1@6U8H#Zu(wGLa_(Esx%h@*pmm5Y9OX@CY`3kPYPQx@z8yAgtm(+agDU%4?c zy8pR4SYbu8vY?JX6HgVq7|f=?w(%`m-C+a@E{euXo>XrGmkmFGzktI*rj*8D z)O|CHKXEzH{~iS+6)%ybRD|JRQ6j<+u_+=SgnJP%K+4$st+~XCVcAjI9e5`RYq$n{ zzy!X9Nv7>T4}}BZpSj9G9|(4ei-}Du<_IZw+CB`?fd$w^;=j8?vlp(#JOWiHaXJjB0Q00RHJ@sG6N#y^H7t^&V} z;VrDI4?75G$q5W9mV=J2iP24NHJy&d|HWHva>FaS#3AO?+ohh1__FMx;?`f{HG3v0 ztiO^Wanb>U4m9eLhoc_2B(ca@YdnHMB*~aYO+AE(&qh@?WukLbf_y z>*3?Xt-lxr?#}y%kTv+l8;!q?Hq8XSU+1E8x~o@9$)zO2z9K#(t`vPDri`mKhv|sh z{KREcy`#pnV>cTT7dm7M9B@9qJRt3lfo(C`CNkIq@>|2<(yn!AmVN?ST zbX_`JjtWa3&N*U{K7FYX8})*D#2@KBae` zhKS~s!r%SrXdhCsv~sF}7?ocyS?afya6%rDBu6g^b2j#TOGp^1zrMR}|70Z>CeYq- z1o|-=FBKlu{@;pm@QQJ_^!&hzi;0Z_Ho){x3O1KQ#TYk=rAt9`YKC0Y^}8GWIN{QW znYJyVTrmNvl!L=YS1G8BAxGmMUPi+Q7yb0XfG`l+L1NQVSbe^BICYrD;^(rke{jWCEZOtVv3xFze!=Z&(7}!)EcN;v0Dbit?RJ6bOr;N$ z=nk8}H<kCEE+IK3z<+3mkn4q!O7TMWpKShWWWM)X*)m6k%3luF6c>zOsFccvfLWf zH+mNkh!H@vR#~oe=ek}W3!71z$Dlj0c(%S|sJr>rvw!x;oCek+8f8s!U{DmfHcNpO z9>(IKOMfJwv?ey`V2ysSx2Npeh_x#bMh)Ngdj$al;5~R7Ac5R2?*f{hI|?{*$0qU- zY$6}ME%OGh^zA^z9zJUs-?a4ni8cw_{cYED*8x{bWg!Fn9)n;E9@B+t;#k}-2_j@# zg#b%R(5_SJAOtfgFCBZc`n<&z6)%nOIu@*yo!a% zpLg#36KBN$01W{b;qWN`Tp(T#jh%;Zp_zpS64lvBVY2B#UK)p`B4Oo)IO3Z&D6<3S zfF?ZdeNEnzE{}#gyuv)>;z6V{!#bx)` zY;hL*f(WVD*D9A4$WbRKF2vf;MoZVdhfWbWhr{+Db5@M^A4wrFReuWWimA4qp`GgoL2`W4WPUL5A=y3Y3P z%G?8lLUhqo@wJW8VDT`j&%YY7xh51NpVYlsrk_i4J|pLO(}(b8_>%U2M`$iVRDc-n zQiOdJbroQ%*vhN{!{pL~N|cfGooK_jTJCA3g_qs4c#6a&_{&$OoSQr_+-O^mKP=Fu zGObEx`7Qyu{nHTGNj(XSX*NPtAILL(0%8Jh)dQh+rtra({;{W2=f4W?Qr3qHi*G6B zOEj7%nw^sPy^@05$lOCjAI)?%B%&#cZ~nC|=g1r!9W@C8T0iUc%T*ne z)&u$n>Ue3FN|hv+VtA+WW)odO-sdtDcHfJ7s&|YCPfWaVHpTGN46V7Lx@feE#Od%0XwiZy40plD%{xl+K04*se zw@X4&*si2Z_0+FU&1AstR)7!Th(fdaOlsWh`d!y=+3m!QC$Zlkg8gnz!}_B7`+wSz z&kD?6{zPnE3uo~Tv8mLP%RaNt2hcCJBq=0T>%MW~Q@Tpt2pPP1?KcywH>in5@ zx+5;xu-ltFfo5vLU;2>r$-KCHjwGR&1XZ0YNyrXXAUK!FLM_7mV&^;;X^*YH(FLRr z`0Jjg7wiq2bisa`CG%o9i)o1`uG?oFjU_Zrv1S^ipz$G-lc^X@~6*)#%nn+RbgksJfl{w=k31(q>7a!PCMp5YY{+Neh~mo zG-3dd!0cy`F!nWR?=9f_KP$X?Lz&cLGm_ohy-|u!VhS1HG~e7~xKpYOh=GmiiU;nu zrZ5tWfan3kp-q_vO)}vY6a$19Q6UL0r znJ+iSHN-&w@vDEZ0V%~?(XBr|jz&vrBNLOngULxtH(Rp&U*rMY42n;05F11xh?k;n_DX2$4|vWIkXnbwfC z=ReH=(O~a;VEgVO?>qsP*#eOC9Y<_9Yt<6X}X{PyF7UXIA$f)>NR5P&4G_Ygq(9TwwQH*P>Rq>3T4I+t2X(b5ogXBAfNf!xiF#Gilm zp2h{&D4k!SkKz-SBa%F-ZoVN$7GX2o=(>vkE^j)BDSGXw?^%RS9F)d_4}PN+6MlI8*Uk7a28CZ)Gp*EK)`n5i z){aq=0SFSO-;sw$nAvJU-$S-cW?RSc7kjEBvWDr1zxb1J7i;!i+3PQwb=)www?7TZ zE~~u)vO>#55eLZW;)F(f0KFf8@$p)~llV{nO7K_Nq-+S^h%QV_CnXLi)p*Pq&`s!d zK2msiR;Hk_rO8`kqe_jfTmmv|$MMo0ll}mI)PO4!ikVd(ZThhi&4ZwK?tD-}noj}v zBJ?jH-%VS|=t)HuTk?J1XaDUjd_5p1kPZi6y#F6$lLeRQbj4hsr=hX z4tXkX2d5DeLMcAYTeYm|u(XvG5JpW}hcOs4#s8g#ihK%@hVz|kL=nfiBqJ{*E*WhC zht3mi$P3a(O5JiDq$Syu9p^HY&9~<#H89D8 zJm84@%TaL_BZ+qy8+T3_pG7Q%z80hnjN;j>S=&WZWF48PDD%55lVuC0%#r5(+S;WH zS7!HEzmn~)Ih`gE`faPRjPe^t%g=F ztpGVW=Cj5ZkpghCf~`ar0+j@A=?3(j@7*pq?|9)n*B4EQTA1xj<+|(Y72?m7F%&&& zdO44owDBPT(8~RO=dT-K4#Ja@^4_0v$O3kn73p6$s?mCmVDUZ+Xl@QcpR6R3B$=am z%>`r9r2Z79Q#RNK?>~lwk^nQlR=Hr-ji$Ss3ltbmB)x@0{VzHL-rxVO(++@Yr@Iu2 zTEX)_9sVM>cX$|xuqz~Y8F-(n;KLAfi*63M7mh&gsPR>N0pd9h!0bm%nA?Lr zS#iEmG|wQd^BSDMk0k?G>S-uE$vtKEF8Dq}%vLD07zK4RLoS?%F1^oZZI$0W->7Z# z?v&|a`u#UD=_>i~`kzBGaPj!mYX5g?3RC4$5EV*j0sV)>H#+$G6!ci=6`)85LWR=FCp-NUff`;2zG9nU6F~ z;3ZyE*>*LvUgae+uMf}aV}V*?DCM>{o31+Sx~6+sz;TI(VmIpDrN3z+BUj`oGGgLP z>h9~MP}Pw#YwzfGP8wSkz`V#}--6}7S9yZvb{;SX?6PM_KuYpbi~*=teZr-ga2QqIz{QrEyZ@>eN*qmy;N@FCBbRNEeeoTmQyrX;+ zCkaJ&vOIbc^2BD6_H+Mrcl?Nt7O{xz9R_L0ZPV_u!sz+TKbXmhK)0QWoe-_HwtKJ@@7=L+ z+K8hhf=4vbdg3GqGN<;v-SMIzvX=Z`WUa_91Yf89^#`G(f-Eq>odB^p-Eqx}ENk#&MxJ+%~Ad2-*`1LNT>2INPw?*V3&kE;tt?rQyBw? zI+xJD04GTz1$7~KMnfpkPRW>f%n|0YCML@ODe`10;^DXX-|Hb*IE%_Vi#Pn9@#ufA z_8NY*1U%VseqYrSm?%>F@`laz+f?+2cIE4Jg6 z_VTcx|DSEA`g!R%RS$2dSRM|9VQClsW-G<~=j5T`pTbu-x6O`R z98b;}`rPM(2={YiytrqX+uh65f?%XiPp`;4CcMT*E*dQJ+if9^D>c_Dk8A(cE<#r=&!& z_`Z01=&MEE+2@yr!|#El=yM}v>i=?w^2E_FLPy(*4A9XmCNy>cBWdx3U>1RylsItO z4V8T$z3W-qqq*H`@}lYpfh=>C!tieKhoMGUi)EpWDr;yIL&fy};Y&l|)f^QE*k~4C zH>y`Iu%#S)z)YUqWO%el*Z)ME#p{1_8-^~6UF;kBTW zMQ!eXQuzkR#}j{qb(y9^Y!X7&T}}-4$%4w@w=;w+>Z%uifR9OoQ>P?0d9xpcwa>7kTv2U zT-F?3`Q`7xOR!gS@j>7In>_h){j#@@(ynYh;nB~}+N6qO(JO1xA z@59Pxc#&I~I64slNR?#hB-4XE>EFU@lUB*D)tu%uEa))B#eJ@ZOX0hIulfnDQz-y8 z`CX@(O%_VC{Ogh&ot``jlDL%R!f>-8yq~oLGxBO?+tQb5%k@a9zTs!+=NOwSVH-cR zqFo^jHeXDA_!rx$NzdP;>{-j5w3QUrR<;}=u2|FBJ;D#v{SK@Z6mjeV7_kFmWt95$ zeGaF{IU?U>?W`jzrG_9=9}yN*LKyzz))PLE+)_jc#4Rd$yFGol;NIk(qO1$5VXR)+ zxF7%f4=Q!NzR>DVXUB&nUT&>Nyf+5QRF+Z`X-bB*7=`|Go5D1&h~ zflKLw??kpiRm0h3|1GvySC2^#kcFz^5{79KKlq@`(leBa=_4CgV9sSHr{RIJ^KwR_ zY??M}-x^=MD+9`v@I3jue=OCn0kxno#6i>b(XKk_XTp_LpI}X*UA<#* zsgvq@yKTe_dTh>q1aeae@8yur08S(Q^8kXkP_ty48V$pX#y9)FQa~E7P7}GP_CbCm zc2dQxTeW(-~Y6}im24*XOC8ySfH*HMEnW3 z4CXp8iK(Nk<^D$g0kUW`8PXn2kdcDk-H@P0?G8?|YVlIFb?a>QunCx%B9TzsqQQ~HD!UO7zq^V!v9jho_FUob&Hxi ztU1nNOK)a!gkb-K4V^QVX05*>-^i|{b`hhvQLyj`E1vAnj0fbqqO%r z6Q;X1x0dL~GqMv%8QindZ4CZ%7pYQW~ z9)I*#Gjref-q(4Z*E#1c&rE0-_(4;_M(V7rgH_7H;ps1s%GBmU z{4a|X##j#XUF2n({v?ZUUAP5k>+)^F)7n-npbV3jAlY8V3*W=fwroDS$c&r$>8aH` zH+irV{RG3^F3oW2&E%5hXgMH9>$WlqX76Cm+iFmFC-DToTa`AcuN9S!SB+BT-IA#3P)JW1m~Cuwjs`Ep(wDXE4oYmt*aU z!Naz^lM}B)JFp7ejro7MU9#cI>wUoi{lylR2~s)3M!6a=_W~ITXCPd@U9W)qA5(mdOf zd3PntGPJyRX<9cgX?(9~TZB5FdEHW~gkJXY51}?s4ZT_VEdwOwD{T2E-B>oC8|_ZwsPNj=-q(-kwy%xX2K0~H z{*+W`-)V`7@c#Iuaef=?RR2O&x>W0A^xSwh5MsjTz(DVG-EoD@asu<>72A_h<39_# zawWVU<9t{r*e^u-5Q#SUI6dV#p$NYEGyiowT>>d*or=Ps!H$-3={bB|An$GPkP5F1 zTnu=ktmF|6E*>ZQvk^~DX(k!N`tiLut*?3FZhs$NUEa4ccDw66-~P;x+0b|<!ZN7Z%A`>2tN#CdoG>((QR~IV_Gj^Yh%!HdA~4C3jOXaqb6Ou z21T~Wmi9F6(_K0@KR@JDTh3-4mv2=T7&ML<+$4;b9SAtv*Uu`0>;VVZHB{4?aIl3J zL(rMfk?1V@l)fy{J5DhVlj&cWKJCcrpOAad(7mC6#%|Sn$VwMjtx6RDx1zbQ|Ngg8N&B56DGhu;dYg$Z{=YmCNn+?ceDclp65c_RnKs4*vefnhudSlrCy6-96vSB4_sFAj# zftzECwmNEOtED^NUt{ZDjT7^g>k1w<=af>+0)%NA;IPq6qx&ya7+QAu=pk8t>KTm` zEBj9J*2t|-(h)xc>Us*jHs)w9qmA>8@u21UqzKk*Ei#0kCeW6o z-2Q+Tvt25IUkb}-_LgD1_FUJ!U8@8OC^9(~Kd*0#zr*8IQkD)6Keb(XFai5*DYf~` z@U?-{)9X&BTf!^&@^rjmvea#9OE~m(D>qfM?CFT9Q4RxqhO0sA7S)=--^*Q=kNh7Y zq%2mu_d_#23d`+v`Ol263CZ<;D%D8Njj6L4T`S*^{!lPL@pXSm>2;~Da- zBX97TS{}exvSva@J5FJVCM$j4WDQuME`vTw>PWS0!;J7R+Kq zVUy6%#n5f7EV(}J#FhDpts;>=d6ow!yhJj8j>MJ@Wr_?x30buuutIG97L1A*QFT$c ziC5rBS;#qj=~yP-yWm-p(?llTwDuhS^f&<(9vA9@UhMH2-Fe_YAG$NvK6X{!mvPK~ zuEA&PA}meylmaIbbJXDOzuIn8cJNCV{tUA<$Vb?57JyAM`*GpEfMmFq>)6$E(9e1@W`l|R%-&}38#bl~levA#fx2wiBk^)mPj?<=S&|gv zQO)4*91$n08@W%2b|QxEiO0KxABAZC{^4BX^6r>Jm?{!`ZId9jjz<%pl(G5l));*`UU3KfnuXSDj2aP>{ zRIB$9pm7lj3*Xg)c1eG!cb+XGt&#?7yJ@C)(Ik)^OZ5><4u$VLCqZ#q2NMCt5 z6$|VN(RWM;5!JV?-h<JkEZ(SZF zC(6J+>A6Am9H7OlOFq6S62-2&z^Np=#xXsOq0WUKr zY_+Ob|CQd1*!Hirj5rn*=_bM5_zKmq6lG zn*&_=x%?ATxZ8ZTzd%biKY_qyNC#ZQ1vX+vc48N>aJXEjs{Y*3Op`Q7-oz8jyAh>d zNt_qvn`>q9aO~7xm{z`ree%lJ3YHCyC`q`-jUVCn*&NIml!uuMNm|~u3#AV?6kC+B z?qrT?xu2^mobSlzb&m(8jttB^je0mx;TT8}`_w(F11IKz83NLj@OmYDpCU^u?fD{) z&=$ptwVw#uohPb2_PrFX;X^I=MVXPDpqTuYhRa>f-=wy$y3)40-;#EUDYB1~V9t%$ z^^<7Zbs0{eB93Pcy)96%XsAi2^k`Gmnypd-&x4v9rAq<>a(pG|J#+Q>E$FvMLmy7T z5_06W=*ASUyPRfgCeiPIe{b47Hjqpb`9Xyl@$6*ntH@SV^bgH&Fk3L9L=6VQb)Uqa z33u#>ecDo&bK(h1WqSH)b_Th#Tvk&%$NXC@_pg5f-Ma#7q;&0QgtsFO~`V&{1b zbSP*X)jgLtd@9XdZ#2_BX4{X~pS8okF7c1xUhEV9>PZco>W-qz7YMD`+kCGULdK|^ zE7VwQ-at{%&fv`a+b&h`TjzxsyQX05UB~a0cuU-}{*%jR48J+yGWyl3Kdz5}U>;lE zgkba*yI5>xqIPz*Y!-P$#_mhHB!0Fpnv{$k-$xxjLAc`XdmHd1k$V@2QlblfJPrly z*~-4HVCq+?9vha>&I6aRGyq2VUon^L1a)g`-Xm*@bl2|hi2b|UmVYW|b+Gy?!aS-p z86a}Jep6Mf>>}n^*Oca@Xz}kxh)Y&pX$^CFAmi#$YVf57X^}uQD!IQSN&int=D> zJ>_|au3Be?hmPKK)1^JQ(O29eTf`>-x^jF2xYK6j_9d_qFkWHIan5=7EmDvZoQWz5 zZGb<{szHc9Nf@om)K_<=FuLR<&?5RKo3LONFQZ@?dyjemAe4$yDrnD zglU#XYo6|~L+YpF#?deK6S{8A*Ou;9G`cdC4S0U74EW18bc5~4>)<*}?Z!1Y)j;Ot zosEP!pc$O^wud(={WG%hY07IE^SwS-fGbvpP?;l8>H$;}urY2JF$u#$q}E*ZG%fR# z`p{xslcvG)kBS~B*^z6zVT@e}imYcz_8PRzM4GS52#ms5Jg9z~ME+uke`(Tq1w3_6 zxUa{HerS7!Wq&y(<9yyN@P^PrQT+6ij_qW3^Q)I53iIFCJE?MVyGLID!f?QHUi1tq z0)RNIMGO$2>S%3MlBc09l!6_(ECxXTU>$KjWdZX^3R~@3!SB zah5Za2$63;#y!Y}(wg1#shMePQTzfQfXyJ-Tf`R05KYcyvo8UW9-IWGWnzxR6Vj8_la;*-z5vWuwUe7@sKr#Tr51d z2PWn5h@|?QU3>k=s{pZ9+(}oye zc*95N_iLmtmu}H-t$smi49Y&ovX}@mKYt2*?C-i3Lh4*#q5YDg1Mh`j9ovRDf9&& zp_UMQh`|pC!|=}1uWoMK5RAjdTg3pXPCsYmRkWW}^m&)u-*c_st~gcss(`haA)xVw zAf=;s>$`Gq_`A}^MjY_BnCjktBNHY1*gzh(i0BFZ{Vg^F?Pbf`8_clvdZ)5(J4EWzAP}Ba5zX=S(2{gDugTQ3`%!q`h7kYSnwC`zEWeuFlODKiityMaM9u{Z%E@@y1jmZA#ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..13b35eba55c6dabc3aac36f33d859266c18fa0d0 GIT binary patch literal 5680 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5fa40fb3d1e0710331a48de5d256da3f275d GIT binary patch literal 520 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/packages/cross_file/cross_file/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1632cfddf3d9dade342351e627a0a75609fb46 GIT binary patch literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/macos/Runner/Configs/AppInfo.xcconfig b/packages/cross_file/cross_file/example/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 000000000000..e7adb11c6198 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = cross_file_example + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2026 dev.flutter.packages. All rights reserved. diff --git a/packages/cross_file/cross_file/example/macos/Runner/Configs/Debug.xcconfig b/packages/cross_file/cross_file/example/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 000000000000..36b0fd9464f4 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/cross_file/cross_file/example/macos/Runner/Configs/Release.xcconfig b/packages/cross_file/cross_file/example/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 000000000000..dff4f49561c8 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/packages/cross_file/cross_file/example/macos/Runner/Configs/Warnings.xcconfig b/packages/cross_file/cross_file/example/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 000000000000..42bcbf4780b1 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements b/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements new file mode 100644 index 000000000000..dddb8a30c851 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/packages/cross_file/cross_file/example/macos/Runner/Info.plist b/packages/cross_file/cross_file/example/macos/Runner/Info.plist new file mode 100644 index 000000000000..4789daa6a443 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift b/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 000000000000..3cc05eb23491 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements b/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements new file mode 100644 index 000000000000..852fa1a4728a --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 000000000000..61f3bd1fc504 --- /dev/null +++ b/packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/packages/cross_file/cross_file/example/web/favicon.png b/packages/cross_file/cross_file/example/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/web/icons/Icon-192.png b/packages/cross_file/cross_file/example/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/web/icons/Icon-512.png b/packages/cross_file/cross_file/example/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/web/icons/Icon-maskable-192.png b/packages/cross_file/cross_file/example/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/web/icons/Icon-maskable-512.png b/packages/cross_file/cross_file/example/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/web/index.html b/packages/cross_file/cross_file/example/web/index.html new file mode 100644 index 000000000000..d38ee3a2d575 --- /dev/null +++ b/packages/cross_file/cross_file/example/web/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + cross_file_example + + + + + + + diff --git a/packages/cross_file/cross_file/example/web/manifest.json b/packages/cross_file/cross_file/example/web/manifest.json new file mode 100644 index 000000000000..fc8c8efa0ca4 --- /dev/null +++ b/packages/cross_file/cross_file/example/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "cross_file_example", + "short_name": "cross_file_example", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/packages/cross_file/cross_file/example/windows/CMakeLists.txt b/packages/cross_file/cross_file/example/windows/CMakeLists.txt new file mode 100644 index 000000000000..182e405d908b --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(cross_file_example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "cross_file_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/cross_file/cross_file/example/windows/flutter/CMakeLists.txt b/packages/cross_file/cross_file/example/windows/flutter/CMakeLists.txt new file mode 100644 index 000000000000..903f4899d6fc --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake b/packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000000..b93c4c30c167 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/cross_file/cross_file/example/windows/runner/CMakeLists.txt b/packages/cross_file/cross_file/example/windows/runner/CMakeLists.txt new file mode 100644 index 000000000000..394917c053a0 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/packages/cross_file/cross_file/example/windows/runner/Runner.rc b/packages/cross_file/cross_file/example/windows/runner/Runner.rc new file mode 100644 index 000000000000..4396895be5b3 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "dev.flutter.packages" "\0" + VALUE "FileDescription", "cross_file_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "cross_file_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 dev.flutter.packages. All rights reserved." "\0" + VALUE "OriginalFilename", "cross_file_example.exe" "\0" + VALUE "ProductName", "cross_file_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp b/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp new file mode 100644 index 000000000000..955ee3038f98 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/packages/cross_file/cross_file/example/windows/runner/flutter_window.h b/packages/cross_file/cross_file/example/windows/runner/flutter_window.h new file mode 100644 index 000000000000..6da0652f05f2 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/cross_file/cross_file/example/windows/runner/main.cpp b/packages/cross_file/cross_file/example/windows/runner/main.cpp new file mode 100644 index 000000000000..24c271d29c8f --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"cross_file_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/packages/cross_file/cross_file/example/windows/runner/resource.h b/packages/cross_file/cross_file/example/windows/runner/resource.h new file mode 100644 index 000000000000..66a65d1e4a79 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/packages/cross_file/cross_file/example/windows/runner/resources/app_icon.ico b/packages/cross_file/cross_file/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file/example/windows/runner/runner.exe.manifest b/packages/cross_file/cross_file/example/windows/runner/runner.exe.manifest new file mode 100644 index 000000000000..153653e8d67f --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/packages/cross_file/cross_file/example/windows/runner/utils.cpp b/packages/cross_file/cross_file/example/windows/runner/utils.cpp new file mode 100644 index 000000000000..3a0b46511a71 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/packages/cross_file/cross_file/example/windows/runner/utils.h b/packages/cross_file/cross_file/example/windows/runner/utils.h new file mode 100644 index 000000000000..3879d5475579 --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp b/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp new file mode 100644 index 000000000000..60608d0fe5bf --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/packages/cross_file/cross_file/example/windows/runner/win32_window.h b/packages/cross_file/cross_file/example/windows/runner/win32_window.h new file mode 100644 index 000000000000..e901dde684ea --- /dev/null +++ b/packages/cross_file/cross_file/example/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ From d4bb9c86c911e6d94fdc2d249a8d88caf6308313 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 5 Feb 2026 14:53:38 -0500 Subject: [PATCH 123/398] add txt file --- packages/cross_file/cross_file/example/assets/hello.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/cross_file/cross_file/example/assets/hello.txt diff --git a/packages/cross_file/cross_file/example/assets/hello.txt b/packages/cross_file/cross_file/example/assets/hello.txt new file mode 100644 index 000000000000..5dd01c177f5d --- /dev/null +++ b/packages/cross_file/cross_file/example/assets/hello.txt @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file From 224ac8c72e55f5bca93aeab0c4f2013702237ad4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 5 Feb 2026 16:58:09 -0500 Subject: [PATCH 124/398] update pubspec but no work --- .../cross_file/cross_file_android/example/pubspec.yaml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index cbe5b4fca13c..71e51754894e 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -29,4 +29,11 @@ dev_dependencies: sdk: flutter flutter: - uses-material-design: true \ No newline at end of file + uses-material-design: true + +dependency_overrides: + file_selector: + git: + url: https://github.com/bparrishMines/packages + ref: new_file_selector + path: packages/file_selector/file_selector \ No newline at end of file From f91cc3224aebdcc578127995168431760cfae39e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:16:35 -0500 Subject: [PATCH 125/398] update to github dependencies --- .../cross_file/example/pubspec.yaml | 6 +++++- packages/cross_file/cross_file/pubspec.yaml | 20 +++++++++++++++---- .../cross_file_android/example/pubspec.yaml | 13 +++++------- .../cross_file_android/pubspec.yaml | 10 ++++++++-- .../cross_file_darwin/example/pubspec.yaml | 6 +++++- .../cross_file/cross_file_darwin/pubspec.yaml | 10 ++++++++-- .../cross_file/cross_file_io/pubspec.yaml | 5 ++++- 7 files changed, 51 insertions(+), 19 deletions(-) diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index 26df1875431e..f6f195f13956 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -14,7 +14,11 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - #file_selector: ^1.1.0 + file_selector: + git: + url: https://github.com/bparrishMines/packages + ref: new_file_selector + path: packages/file_selector/file_selector flutter: sdk: flutter flutter_driver: diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index 2f873016f8dd..54c7a68eb667 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -26,13 +26,25 @@ flutter: dependencies: cross_file_android: - path: ../cross_file_android + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_android cross_file_darwin: - path: ../cross_file_darwin + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_darwin cross_file_io: - path: ../cross_file_io + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_io cross_file_platform_interface: - path: ../cross_file_platform_interface + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface flutter: sdk: flutter diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 71e51754894e..5031c8112dbc 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -14,7 +14,11 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - file_selector: ^1.1.0 + file_selector: + git: + url: https://github.com/bparrishMines/packages + ref: new_file_selector + path: packages/file_selector/file_selector flutter: sdk: flutter flutter_driver: @@ -30,10 +34,3 @@ dev_dependencies: flutter: uses-material-design: true - -dependency_overrides: - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector \ No newline at end of file diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 01df121bbcc9..f9ac645c614a 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -19,9 +19,15 @@ flutter: dependencies: cross_file_io: - path: ../cross_file_io + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_io cross_file_platform_interface: - path: ../cross_file_platform_interface + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface flutter: sdk: flutter diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index e42ac86165c9..8f938bd02383 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -15,7 +15,11 @@ dependencies: # the parent directory to use the current plugin's version. path: ../ cupertino_icons: ^1.0.8 - file_selector: ^1.1.0 + file_selector: + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/file_selector/file_selector flutter: sdk: flutter mime: ^2.0.0 diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index f6af898738d6..1c3b8b24ca32 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -23,9 +23,15 @@ flutter: dependencies: cross_file_io: - path: ../cross_file_io + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_io cross_file_platform_interface: - path: ../cross_file_platform_interface + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface flutter: sdk: flutter path: ^1.9.1 diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index af4afd3c78fd..2d86192404a2 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -19,7 +19,10 @@ flutter: dependencies: cross_file_platform_interface: - path: ../cross_file_platform_interface + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface flutter: sdk: flutter path: ^1.9.1 From 3420f3da97cb04f63f161eea05bee118bcfeae9f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:17:50 -0500 Subject: [PATCH 126/398] example version solved --- packages/cross_file/cross_file/example/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index f6f195f13956..372b96c87841 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -13,7 +13,10 @@ dependencies: # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - path: ../ + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file file_selector: git: url: https://github.com/bparrishMines/packages From e825b1a0a4b9866c032cf9d668c22509846c24ff Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:18:32 -0500 Subject: [PATCH 127/398] delet e cross_file_ios --- packages/cross_file/cross_file_ios/.gitignore | 33 - packages/cross_file/cross_file_ios/.metadata | 30 - .../cross_file/cross_file_ios/CHANGELOG.md | 3 - packages/cross_file/cross_file_ios/LICENSE | 1 - packages/cross_file/cross_file_ios/README.md | 15 - .../cross_file_ios/analysis_options.yaml | 4 - .../cross_file_ios/example/.gitignore | 45 - .../cross_file_ios/example/README.md | 16 - .../example/analysis_options.yaml | 28 - .../plugin_integration_test.dart | 25 - .../cross_file_ios/example/ios/.gitignore | 34 - .../ios/Flutter/AppFrameworkInfo.plist | 24 - .../example/ios/Flutter/Debug.xcconfig | 2 - .../example/ios/Flutter/Release.xcconfig | 2 - .../cross_file_ios/example/ios/Podfile | 43 - .../ios/Runner.xcodeproj/project.pbxproj | 731 -------- .../contents.xcworkspacedata | 7 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../xcshareddata/xcschemes/Runner.xcscheme | 101 -- .../contents.xcworkspacedata | 10 - .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../xcshareddata/WorkspaceSettings.xcsettings | 8 - .../example/ios/Runner/AppDelegate.swift | 16 - .../AppIcon.appiconset/Contents.json | 122 -- .../Icon-App-1024x1024@1x.png | Bin 10932 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 295 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 406 -> 0 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 450 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 282 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 462 -> 0 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 704 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 406 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 586 -> 0 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 862 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 862 -> 0 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 1674 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 762 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 1226 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 1418 -> 0 bytes .../LaunchImage.imageset/Contents.json | 23 - .../LaunchImage.imageset/LaunchImage.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 68 -> 0 bytes .../LaunchImage.imageset/README.md | 5 - .../Runner/Base.lproj/LaunchScreen.storyboard | 37 - .../ios/Runner/Base.lproj/Main.storyboard | 26 - .../example/ios/Runner/Info.plist | 70 - .../ios/Runner/Runner-Bridging-Header.h | 1 - .../ios/RunnerTests/FileHandleTests.swift | 37 - .../ios/RunnerTests/FileManagerTests.swift | 69 - .../example/ios/RunnerTests/RunnerTests.swift | 26 - ...RLResolvingBookmarkDataResponseTests.swift | 31 - .../example/ios/RunnerTests/UrlTests.swift | 82 - .../cross_file_ios/example/lib/main.dart | 104 -- .../cross_file_ios/example/pubspec.yaml | 32 - .../example/test/widget_test.dart | 27 - .../cross_file/cross_file_ios/ios/.gitignore | 38 - .../cross_file_ios/ios/Assets/.gitkeep | 0 .../ios/Classes/CrossFileIOSPlugin.swift | 23 - .../ios/Classes/ProxyAPIDelegate.swift | 33 - .../URLResolvingBookmarkDataResponse.swift | 9 - .../proxies/FileHandleProxyAPIDelegate.swift | 50 - .../proxies/FileManagerProxyAPIDelegate.swift | 47 - .../ios/Classes/proxies/Foundation.g.swift | 1611 ----------------- .../Classes/proxies/URLProxyAPIDelegate.swift | 53 - ...BookmarkDataResponseProxyAPIDelegate.swift | 28 - .../ios/Resources/PrivacyInfo.xcprivacy | 14 - .../cross_file_ios/ios/cross_file_ios.podspec | 29 - .../cross_file_ios/lib/cross_file_ios.dart | 4 - .../lib/src/cross_file_ios.dart | 24 - .../cross_file_ios/lib/src/foundation.g.dart | 1318 -------------- .../lib/src/ios_cross_file.dart | 142 -- .../cross_file_ios/pigeons/copyright.txt | 3 - .../cross_file_ios/pigeons/foundation.dart | 70 - .../cross_file/cross_file_ios/pubspec.yaml | 31 - .../cross_file_ios_method_channel_test.dart | 27 - .../test/cross_file_ios_test.dart | 29 - 78 files changed, 5477 deletions(-) delete mode 100644 packages/cross_file/cross_file_ios/.gitignore delete mode 100644 packages/cross_file/cross_file_ios/.metadata delete mode 100644 packages/cross_file/cross_file_ios/CHANGELOG.md delete mode 100644 packages/cross_file/cross_file_ios/LICENSE delete mode 100644 packages/cross_file/cross_file_ios/README.md delete mode 100644 packages/cross_file/cross_file_ios/analysis_options.yaml delete mode 100644 packages/cross_file/cross_file_ios/example/.gitignore delete mode 100644 packages/cross_file/cross_file_ios/example/README.md delete mode 100644 packages/cross_file/cross_file_ios/example/analysis_options.yaml delete mode 100644 packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart delete mode 100644 packages/cross_file/cross_file_ios/example/ios/.gitignore delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Podfile delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist delete mode 100644 packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h delete mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift delete mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift delete mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift delete mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift delete mode 100644 packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift delete mode 100644 packages/cross_file/cross_file_ios/example/lib/main.dart delete mode 100644 packages/cross_file/cross_file_ios/example/pubspec.yaml delete mode 100644 packages/cross_file/cross_file_ios/example/test/widget_test.dart delete mode 100644 packages/cross_file/cross_file_ios/ios/.gitignore delete mode 100644 packages/cross_file/cross_file_ios/ios/Assets/.gitkeep delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy delete mode 100644 packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec delete mode 100644 packages/cross_file/cross_file_ios/lib/cross_file_ios.dart delete mode 100644 packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart delete mode 100644 packages/cross_file/cross_file_ios/lib/src/foundation.g.dart delete mode 100644 packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart delete mode 100644 packages/cross_file/cross_file_ios/pigeons/copyright.txt delete mode 100644 packages/cross_file/cross_file_ios/pigeons/foundation.dart delete mode 100644 packages/cross_file/cross_file_ios/pubspec.yaml delete mode 100644 packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart delete mode 100644 packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart diff --git a/packages/cross_file/cross_file_ios/.gitignore b/packages/cross_file/cross_file_ios/.gitignore deleted file mode 100644 index b9d7f25b91b6..000000000000 --- a/packages/cross_file/cross_file_ios/.gitignore +++ /dev/null @@ -1,33 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. -/pubspec.lock -**/doc/api/ -.dart_tool/ -.flutter-plugins-dependencies -/build/ -/coverage/ diff --git a/packages/cross_file/cross_file_ios/.metadata b/packages/cross_file/cross_file_ios/.metadata deleted file mode 100644 index d99a0a7fe63c..000000000000 --- a/packages/cross_file/cross_file_ios/.metadata +++ /dev/null @@ -1,30 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: "81928eeb91fcdb2bc7a2dc35622627b31581549f" - channel: "main" - -project_type: plugin - -# Tracks metadata for the flutter migrate command -migration: - platforms: - - platform: root - create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - - platform: ios - create_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - base_revision: 81928eeb91fcdb2bc7a2dc35622627b31581549f - - # User provided section - - # List of Local paths (relative to this file) that should be - # ignored by the migrate tool. - # - # Files that are not part of the templates will be ignored by default. - unmanaged_files: - - 'lib/main.dart' - - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/cross_file/cross_file_ios/CHANGELOG.md b/packages/cross_file/cross_file_ios/CHANGELOG.md deleted file mode 100644 index 41cc7d8192ec..000000000000 --- a/packages/cross_file/cross_file_ios/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -## 0.0.1 - -* TODO: Describe initial release. diff --git a/packages/cross_file/cross_file_ios/LICENSE b/packages/cross_file/cross_file_ios/LICENSE deleted file mode 100644 index ba75c69f7f21..000000000000 --- a/packages/cross_file/cross_file_ios/LICENSE +++ /dev/null @@ -1 +0,0 @@ -TODO: Add your license here. diff --git a/packages/cross_file/cross_file_ios/README.md b/packages/cross_file/cross_file_ios/README.md deleted file mode 100644 index 43322a17da3e..000000000000 --- a/packages/cross_file/cross_file_ios/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# cross_file_ios - -A new Flutter plugin project. - -## Getting Started - -This project is a starting point for a Flutter -[plug-in package](https://flutter.dev/to/develop-plugins), -a specialized package that includes platform-specific implementation code for -Android and/or iOS. - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev), which offers tutorials, -samples, guidance on mobile development, and a full API reference. - diff --git a/packages/cross_file/cross_file_ios/analysis_options.yaml b/packages/cross_file/cross_file_ios/analysis_options.yaml deleted file mode 100644 index a5744c1cfbe7..000000000000 --- a/packages/cross_file/cross_file_ios/analysis_options.yaml +++ /dev/null @@ -1,4 +0,0 @@ -include: package:flutter_lints/flutter.yaml - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_ios/example/.gitignore b/packages/cross_file/cross_file_ios/example/.gitignore deleted file mode 100644 index 3820a95c65c3..000000000000 --- a/packages/cross_file/cross_file_ios/example/.gitignore +++ /dev/null @@ -1,45 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.build/ -.buildlog/ -.history -.svn/ -.swiftpm/ -migrate_working_dir/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -**/ios/Flutter/.last_build_id -.dart_tool/ -.flutter-plugins-dependencies -.pub-cache/ -.pub/ -/build/ -/coverage/ - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Android Studio will place build artifacts here -/android/app/debug -/android/app/profile -/android/app/release diff --git a/packages/cross_file/cross_file_ios/example/README.md b/packages/cross_file/cross_file_ios/example/README.md deleted file mode 100644 index d1ba652b9015..000000000000 --- a/packages/cross_file/cross_file_ios/example/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# cross_file_ios_example - -Demonstrates how to use the cross_file_ios plugin. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) - -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/packages/cross_file/cross_file_ios/example/analysis_options.yaml b/packages/cross_file/cross_file_ios/example/analysis_options.yaml deleted file mode 100644 index 0d2902135cae..000000000000 --- a/packages/cross_file/cross_file_ios/example/analysis_options.yaml +++ /dev/null @@ -1,28 +0,0 @@ -# This file configures the analyzer, which statically analyzes Dart code to -# check for errors, warnings, and lints. -# -# The issues identified by the analyzer are surfaced in the UI of Dart-enabled -# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be -# invoked from the command line by running `flutter analyze`. - -# The following line activates a set of recommended lints for Flutter apps, -# packages, and plugins designed to encourage good coding practices. -include: package:flutter_lints/flutter.yaml - -linter: - # The lint rules applied to this project can be customized in the - # section below to disable rules from the `package:flutter_lints/flutter.yaml` - # included above or to enable additional rules. A list of all available lints - # and their documentation is published at https://dart.dev/lints. - # - # Instead of disabling a lint rule for the entire project in the - # section below, it can also be suppressed for a single line of code - # or a specific dart file by using the `// ignore: name_of_lint` and - # `// ignore_for_file: name_of_lint` syntax on the line or in the file - # producing the lint. - rules: - # avoid_print: false # Uncomment to disable the `avoid_print` rule - # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule - -# Additional information about this file can be found at -# https://dart.dev/guides/language/analysis-options diff --git a/packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart deleted file mode 100644 index ad1fbfaa88ad..000000000000 --- a/packages/cross_file/cross_file_ios/example/integration_test/plugin_integration_test.dart +++ /dev/null @@ -1,25 +0,0 @@ -// This is a basic Flutter integration test. -// -// Since integration tests run in a full Flutter application, they can interact -// with the host side of a plugin implementation, unlike Dart unit tests. -// -// For more information about Flutter integration tests, please see -// https://flutter.dev/to/integration-testing - - -import 'package:flutter_test/flutter_test.dart'; -import 'package:integration_test/integration_test.dart'; - -import 'package:cross_file_ios/cross_file_ios.dart'; - -void main() { - IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - - testWidgets('getPlatformVersion test', (WidgetTester tester) async { - final CrossFileIos plugin = CrossFileIos(); - final String? version = await plugin.getPlatformVersion(); - // The version string depends on the host platform running the test, so - // just assert that some non-empty string is returned. - expect(version?.isNotEmpty, true); - }); -} diff --git a/packages/cross_file/cross_file_ios/example/ios/.gitignore b/packages/cross_file/cross_file_ios/example/ios/.gitignore deleted file mode 100644 index 7a7f9873ad7d..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -**/dgph -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/ephemeral/ -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist b/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 391a902b2beb..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f3021..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe2000..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_ios/example/ios/Podfile b/packages/cross_file/cross_file_ios/example/ios/Podfile deleted file mode 100644 index 620e46eba607..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 3d6c9f4f3d89..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,731 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 65AF3F910C52DB6D2F3DAE9D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A33FE71D0C42047E84BBCBE6 /* Pods_Runner.framework */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 829E1B841CA9DB7260DC4C16 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E33381F0C94153C78C1AFE19 /* Pods_RunnerTests.framework */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 97C146E61CF9000F007C117D /* Project object */; - proxyType = 1; - remoteGlobalIDString = 97C146ED1CF9000F007C117D; - remoteInfo = Runner; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 078A54601D0283091B1185EA /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 2E1AE5E5601D04A21C0626B7 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8ADA6E46E97DBE1D2BD49E1E /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A33FE71D0C42047E84BBCBE6 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C13A5126E08748B2929C82F3 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - C2EAF8DCAE4A5A64E43C3680 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - E33381F0C94153C78C1AFE19 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - E3676B09D7617ECB65174B4A /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 65AF3F910C52DB6D2F3DAE9D /* Pods_Runner.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - A190650AD74D9C6C68DDAEF2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 829E1B841CA9DB7260DC4C16 /* Pods_RunnerTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; - 77684829B5428D1CBC39FB7E /* Pods */ = { - isa = PBXGroup; - children = ( - C13A5126E08748B2929C82F3 /* Pods-Runner.debug.xcconfig */, - 2E1AE5E5601D04A21C0626B7 /* Pods-Runner.release.xcconfig */, - C2EAF8DCAE4A5A64E43C3680 /* Pods-Runner.profile.xcconfig */, - E3676B09D7617ECB65174B4A /* Pods-RunnerTests.debug.xcconfig */, - 078A54601D0283091B1185EA /* Pods-RunnerTests.release.xcconfig */, - 8ADA6E46E97DBE1D2BD49E1E /* Pods-RunnerTests.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; - 8FB841B256507B5BDE364A3A /* Frameworks */ = { - isa = PBXGroup; - children = ( - A33FE71D0C42047E84BBCBE6 /* Pods_Runner.framework */, - E33381F0C94153C78C1AFE19 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, - 77684829B5428D1CBC39FB7E /* Pods */, - 8FB841B256507B5BDE364A3A /* Frameworks */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - E2980696C569222F2BFF4B05 /* [CP] Check Pods Manifest.lock */, - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - A190650AD74D9C6C68DDAEF2 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - A469FFB3E7F2610761EABEE5 /* [CP] Check Pods Manifest.lock */, - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 138C88CB6F339C47BACAD73B /* [CP] Embed Pods Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 331C8080294A63A400263BE5 = { - CreatedOnToolsVersion = 14.0; - TestTargetID = 97C146ED1CF9000F007C117D; - }; - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 331C807F294A63A400263BE5 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 138C88CB6F339C47BACAD73B /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; - A469FFB3E7F2610761EABEE5 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - E2980696C569222F2BFF4B05 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 331C807D294A63A400263BE5 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 97C146ED1CF9000F007C117D /* Runner */; - targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = PT2QK76LGP; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E3676B09D7617ECB65174B4A /* Pods-RunnerTests.debug.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 078A54601D0283091B1185EA /* Pods-RunnerTests.release.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8ADA6E46E97DBE1D2BD49E1E /* Pods-RunnerTests.profile.xcconfig */; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = PT2QK76LGP; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = PT2QK76LGP; - ENABLE_BITCODE = NO; - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileIosExample; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 919434a6254f..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5ea15..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index e3773d42e24c..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 21a3cc14c74e..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d981003d68..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c5ea15..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift b/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift deleted file mode 100644 index c30b367ec0a9..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Flutter -import UIKit - -@main -@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } - - func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { - GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) - } -} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fab2d9d..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4725e9b0ddb1deab583e5b5102493aa332..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10932 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 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 797d452e458972bab9d994556c8305db4c827017..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 406 zcmV;H0crk;P))>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index 6ed2d933e1120817fe9182483a228007b18ab6ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 450 zcmV;z0X_bSP)iGWQ_5NJQ_~rNh*z)}eT%KUb z`7gNk0#AwF^#0T0?hIa^`~Ck;!}#m+_uT050aTR(J!bU#|IzRL%^UsMS#KsYnTF*!YeDOytlP4VhV?b} z%rz_<=#CPc)tU1MZTq~*2=8~iZ!lSa<{9b@2Jl;?IEV8)=fG217*|@)CCYgFze-x? zIFODUIA>nWKpE+bn~n7;-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGr zXPIdeRE&b2Thd#{MtDK$px*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{Hig)k suLT-RhftRq8b9;(V=235Wa|I=027H2wCDra;{X5v07*qoM6N<$f;9x^2LJ#7 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cd7b0099ca80c806f8fe495613e8d6c69460d76..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282 zcmV+#0p(^bcu7P-R4C8Q z&e;xxFbF_Vrezo%_kH*OKhshZ6BFpG-Y1e10`QXJKbND7AMQ&cMj60B5TNObaZxYybcN07*qoM6N<$g3m;S%K!iX diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index fe730945a01f64a61e2235dbe3f45b08f7729182..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 462 zcmV;<0WtoGP)-}iV`2<;=$?g5M=KQbZ{F&YRNy7Nn@%_*5{gvDM0aKI4?ESmw z{NnZg)A0R`+4?NF_RZexyVB&^^ZvN!{I28tr{Vje;QNTz`dG&Jz0~Ek&f2;*Z7>B|cg}xYpxEFY+0YrKLF;^Q+-HreN0P{&i zK~zY`?b7ECf-n?@;d<&orQ*Q7KoR%4|C>{W^h6@&01>0SKS`dn{Q}GT%Qj_{PLZ_& zs`MFI#j-(>?bvdZ!8^xTwlY{qA)T4QLbY@j(!YJ7aXJervHy6HaG_2SB`6CC{He}f zHVw(fJWApwPq!6VY7r1w-Fs)@ox~N+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9 zR%3*Q+)t%S!MU_`id^@&Y{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&)179 zp<)v6Y}pRl100G2FL_t(o!|l{-Q-VMg#&MKg7c{O0 z2wJImOS3Gy*Z2Qifdv~JYOp;v+U)a|nLoc7hNH;I$;lzDt$}rkaFw1mYK5_0Q(Sut zvbEloxON7$+HSOgC9Z8ltuC&0OSF!-mXv5caV>#bc3@hBPX@I$58-z}(ZZE!t-aOG zpjNkbau@>yEzH(5Yj4kZiMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_st8pKG z(%SHyHdU&v%f36~uERh!bd`!T2dw;z6PrOTQ7Vt*#9F2uHlUVnb#ev_o^fh}Dzmq} zWtlk35}k=?xj28uO|5>>$yXadTUE@@IPpgH`gJ~Ro4>jd1IF|(+IX>8M4Ps{PNvmI zNj4D+XgN83gPt_Gm}`Ybv{;+&yu-C(Grdiahmo~BjG-l&mWM+{e5M1sm&=xduwgM9 z`8OEh`=F3r`^E{n_;%9weN{cf2%7=VzC@cYj+lg>+3|D|_1C@{hcU(DyQG_BvBWe? zvTv``=%b1zrol#=R`JB)>cdjpWt&rLJgVp-t?DREyuq1A%0Z4)6_WsQ7{nzjN zo!X zGXV)2i3kcZIL~_j>uIKPK_zib+3T+Nt3Mb&Br)s)UIaA}@p{wDda>7=Q|mGRp7pqY zkJ!7E{MNz$9nOwoVqpFb)}$IP24Wn2JJ=Cw(!`OXJBr45rP>>AQr$6c7slJWvbpNW z@KTwna6d?PP>hvXCcp=4F;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f*5nx ACIA2c diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index 502f463a9bc882b461c96aadf492d1729e49e725..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 586 zcmV-Q0=4~#P)+}#`wDE{8-2Mebf5<{{PqV{TgVcv*r8?UZ3{-|G?_}T*&y;@cqf{ z{Q*~+qr%%p!1pS*_Uicl#q9lc(D`!D`LN62sNwq{oYw(Wmhk)k<@f$!$@ng~_5)Ru z0Z)trIA5^j{DIW^c+vT2%lW+2<(RtE2wR;4O@)Tm`Xr*?A(qYoM}7i5Yxw>D(&6ou zxz!_Xr~yNF+waPe00049Nkl*;a!v6h%{rlvIH#gW3s8p;bFr=l}mRqpW2h zw=OA%hdyL~z+UHOzl0eKhEr$YYOL-c-%Y<)=j?(bzDweB7{b+%_ypvm_cG{SvM=DK zhv{K@m>#Bw>2W$eUI#iU)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G! zhkE!s;%oku3;IwG3U^2kw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn`0X*2 zy3(k600_CSZj?O$Qu%&$;|TGUJrptR(HzyIx>5E(2r{eA(<6t3e3I0B)7d6s7?Z5J zZ!rtKvA{MiEBm&KFtoifx>5P^Z=vl)95XJn()aS5%ad(s?4-=Tkis9IGu{`Fy8r+H07*qoM6N<$f20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 0ec303439225b78712f49115768196d8d76f6790..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 862 zcmV-k1EKthP)20Z)wqMt%V?S?~D#06};F zA3KcL`Wb+>5ObvgQIG&ig8(;V04hz?@cqy3{mSh8o!|U|)cI!1_+!fWH@o*8vh^CU z^ws0;(c$gI+2~q^tO#GDHf@=;DncUw00J^eL_t(&-tE|HQ`%4vfZ;WsBqu-$0nu1R zq^Vj;p$clf^?twn|KHO+IGt^q#a3X?w9dXC@*yxhv&l}F322(8Y1&=P&I}~G@#h6; z1CV9ecD9ZEe87{{NtI*)_aJ<`kJa z?5=RBtFF50s;jQLFil-`)m2wrb=6h(&brpj%nG_U&ut~$?8Rokzxi8zJoWr#2dto5 zOX_URcc<1`Iky+jc;A%Vzx}1QU{2$|cKPom2Vf1{8m`vja4{F>HS?^Nc^rp}xo+Nh zxd}eOm`fm3@MQC1< zIk&aCjb~Yh%5+Yq0`)D;q{#-Uqlv*o+Oor zE!I71Z@ASH3grl8&P^L0WpavHoP|UX4e?!igT`4?AZk$hu*@%6WJ;zDOGlw7kj@ zY5!B-0ft0f?Lgb>C;$Ke07*qoM6N<$f~t1N9smFU diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index e9f5fea27c705180eb716271f41b582e76dcbd90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1674 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 diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 0467bf12aa4d28f374bb26596605a46dcbb3e7c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1418 zcmV;51$Fv~P)q zKfU)WzW*n(@|xWGCA9ScMt*e9`2kdxPQ&&>|-UCa7_51w+ zLUsW@ZzZSW0y$)Hp~e9%PvP|a03ks1`~K?q{u;6NC8*{AOqIUq{CL&;p56Lf$oQGq z^={4hPQv)y=I|4n+?>7Fim=dxt1 z2H+Dm+1+fh+IF>G0SjJMkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJT zkdTm&kdTm&kdTm&kdP`esgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>Tmf` zm1{eLgw!b{bXkjWbF%dTkTZEJWyWOb##Lfw4EK2}<0d6%>AGS{po>WCOy&f$Tay_> z?NBlkpo@s-O;0V%Y_Xa-G#_O08q5LR*~F%&)}{}r&L%Sbs8AS4t7Y0NEx*{soY=0MZExqA5XHQkqi#4gW3 zqODM^iyZl;dvf)-bOXtOru(s)Uc7~BFx{w-FK;2{`VA?(g&@3z&bfLFyctOH!cVsF z7IL=fo-qBndRUm;kAdXR4e6>k-z|21AaN%ubeVrHl*<|s&Ax@W-t?LR(P-24A5=>a z*R9#QvjzF8n%@1Nw@?CG@6(%>+-0ASK~jEmCV|&a*7-GKT72W<(TbSjf)&Eme6nGE z>Gkj4Sq&2e+-G%|+NM8OOm5zVl9{Z8Dd8A5z3y8mZ=4Bv4%>as_{9cN#bm~;h>62( zdqY93Zy}v&c4n($Vv!UybR8ocs7#zbfX1IY-*w~)p}XyZ-SFC~4w>BvMVr`dFbelV{lLL0bx7@*ZZdebr3`sP;? zVImji)kG)(6Juv0lz@q`F!k1FE;CQ(D0iG$wchPbKZQELlsZ#~rt8#90Y_Xh&3U-< z{s<&cCV_1`^TD^ia9!*mQDq& zn2{r`j};V|uV%_wsP!zB?m%;FeaRe+X47K0e+KE!8C{gAWF8)lCd1u1%~|M!XNRvw zvtqy3iz0WSpWdhn6$hP8PaRBmp)q`#PCA`Vd#Tc$@f1tAcM>f_I@bC)hkI9|o(Iqv zo}Piadq!j76}004RBio<`)70k^`K1NK)q>w?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF z34$0Z;QO!JOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUC YUoZo%k(ykuW&i*H07*qoM6N<$f+CH{y8r+H diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2fd467..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19eacad3b03bb08bbddbbf4ac48dd78b3d838..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b70f1..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c7c939..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard b/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c28516fb38..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist b/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist deleted file mode 100644 index 670b70bea7f6..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Info.plist +++ /dev/null @@ -1,70 +0,0 @@ - - - - - CADisableMinimumFrameDurationOnPhone - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - Cross File Ios - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - cross_file_ios_example - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UIApplicationSceneManifest - - UIApplicationSupportsMultipleScenes - - UISceneConfigurations - - UIWindowSceneSessionRoleApplication - - - UISceneClassName - UIWindowScene - UISceneConfigurationName - flutter - UISceneDelegateClassName - FlutterSceneDelegate - UISceneStoryboardFile - Main - - - - - UIApplicationSupportsIndirectInputEvents - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h b/packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a560b42..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift deleted file mode 100644 index 4b06862f67da..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileHandleTests.swift +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import XCTest - -@testable import cross_file_ios - -class FileHandleTests: XCTestCase { - func testFromReadingFromUrl() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = try? api.pigeonDelegate.fromReadingFromUrl(pigeonApi: api, url: TestURL) - XCTAssertNotNil(instance) - } - - func testReadToEnd() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance) - - XCTAssertTrue(instance.readToEndCalled) - XCTAssertEqual(value, instance.readToEnd()) - } - -} -class TestFileHandle: FileHandle { - var readToEndCalled = false - - override func readToEnd() { - readToEndCalled = true - } -} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift deleted file mode 100644 index e71ae793c861..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/FileManagerTests.swift +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import Foundation -import XCTest - -@testable import cross_file_ios - -class FileManagerTests: XCTestCase { - func testFileExistsAtPath() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let path = "myString" - let value = try? api.pigeonDelegate.fileExistsAtPath( - pigeonApi: api, pigeonInstance: instance, path: path) - - XCTAssertEqual(instance.fileExistsAtPathArgs, [path]) - XCTAssertEqual(value, instance.fileExistsAtPath(path: path)) - } - - func testIsReadableFileAtPath() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let path = "myString" - let value = try? api.pigeonDelegate.isReadableFileAtPath( - pigeonApi: api, pigeonInstance: instance, path: path) - - XCTAssertEqual(instance.isReadableFileAtPathArgs, [path]) - XCTAssertEqual(value, instance.isReadableFileAtPath(path: path)) - } - - func testContentsAtPath() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let path = "myString" - let value = try? api.pigeonDelegate.contentsAtPath( - pigeonApi: api, pigeonInstance: instance, path: path) - - XCTAssertEqual(instance.contentsAtPathArgs, [path]) - XCTAssertEqual(value, instance.contentsAtPath(path: path)) - } - -} -class TestFileManager: FileManager { - var fileExistsAtPathArgs: [AnyHashable?]? = nil - var isReadableFileAtPathArgs: [AnyHashable?]? = nil - var contentsAtPathArgs: [AnyHashable?]? = nil - - override func fileExistsAtPath() { - fileExistsAtPathArgs = [path] - return true - } - override func isReadableFileAtPath() { - isReadableFileAtPathArgs = [path] - return true - } - override func contentsAtPath() { - contentsAtPathArgs = [path] - return byteArrayOf(0xA1.toByte()) - } -} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 5440378e39bc..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,26 +0,0 @@ -import Flutter -import UIKit -import XCTest - -@testable import cross_file_ios - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - -class RunnerTests: XCTestCase { - - func testGetPlatformVersion() { - let plugin = CrossFileIosPlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual(result as! String, "iOS " + UIDevice.current.systemVersion) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) - } - -} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift deleted file mode 100644 index c0c72062fe15..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/URLResolvingBookmarkDataResponseTests.swift +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import XCTest - -@testable import cross_file_ios - -class URLResolvingBookmarkDataResponseTests: XCTestCase { - func testUrl() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) - - let instance = TestURLResolvingBookmarkDataResponse() - let value = try? api.pigeonDelegate.url(pigeonApi: api, pigeonInstance: instance) - - XCTAssertEqual(value, instance.url) - } - - func testIsStale() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) - - let instance = TestURLResolvingBookmarkDataResponse() - let value = try? api.pigeonDelegate.isStale(pigeonApi: api, pigeonInstance: instance) - - XCTAssertEqual(value, instance.isStale) - } - -} diff --git a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift b/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift deleted file mode 100644 index 348d9218779b..000000000000 --- a/packages/cross_file/cross_file_ios/example/ios/RunnerTests/UrlTests.swift +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import XCTest - -@testable import cross_file_ios - -class URLTests: XCTestCase { - func testPath() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - let value = try? api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: instance) - - XCTAssertTrue(instance.pathCalled) - XCTAssertEqual(value, instance.path()) - } - - func testBookmarkData() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - let options = [.minimalBookmark] - let keys = [.isDirectoryKey] - let relativeTo = TestURL - let value = try? api.pigeonDelegate.bookmarkData( - pigeonApi: api, pigeonInstance: instance, options: options, keys: keys, relativeTo: relativeTo - ) - - XCTAssertEqual(instance.bookmarkDataArgs, [options, keys, relativeTo]) - XCTAssertEqual( - value, instance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo)) - } - - func testStartAccessingSecurityScopedResource() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - let value = try? api.pigeonDelegate.startAccessingSecurityScopedResource( - pigeonApi: api, pigeonInstance: instance) - - XCTAssertTrue(instance.startAccessingSecurityScopedResourceCalled) - XCTAssertEqual(value, instance.startAccessingSecurityScopedResource()) - } - - func testStopAccessingSecurityScopedResource() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - try? api.pigeonDelegate.stopAccessingSecurityScopedResource( - pigeonApi: api, pigeonInstance: instance) - - XCTAssertTrue(instance.stopAccessingSecurityScopedResourceCalled) - } - -} -class TestURL: URL { - var pathCalled = false - var bookmarkDataArgs: [AnyHashable?]? = nil - var startAccessingSecurityScopedResourceCalled = false - var stopAccessingSecurityScopedResourceCalled = false - - override func path() { - pathCalled = true - } - override func bookmarkData() { - bookmarkDataArgs = [options, keys, relativeTo] - return byteArrayOf(0xA1.toByte()) - } - override func startAccessingSecurityScopedResource() { - startAccessingSecurityScopedResourceCalled = true - } - override func stopAccessingSecurityScopedResource() { - stopAccessingSecurityScopedResourceCalled = true - } -} diff --git a/packages/cross_file/cross_file_ios/example/lib/main.dart b/packages/cross_file/cross_file_ios/example/lib/main.dart deleted file mode 100644 index 49a2ec5d16c0..000000000000 --- a/packages/cross_file/cross_file_ios/example/lib/main.dart +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:cross_file_ios/cross_file_ios.dart'; -import 'package:file_selector_ios/file_selector_ios.dart'; -import 'package:flutter/material.dart'; -import 'package:mime/mime.dart' as mime; - -void main() { - runApp(const MaterialApp(home: FileOpenScreen())); -} - -/// Example screen to open a file selector and display it. -class FileOpenScreen extends StatelessWidget { - /// Constructs a [FileOpenScreen]. - const FileOpenScreen({super.key}); - - Future _openFile(BuildContext context) async { - final IOSXFile? file = await FileSelectorIOS().openFile2(); - - if (!context.mounted) { - return; - } - - print(file?.params.uri); - - if (file case final IOSXFile file) { - switch (mime.lookupMimeType(file.params.uri)) { - case final String mimeType when mimeType.startsWith('text'): - await showDialog( - context: context, - builder: (BuildContext context) => TextDisplay(file), - ); - case final String mimeType when mimeType.startsWith('image'): - case final String mimeType when mimeType.startsWith('application'): - case null: - debugPrint('Unsupported file type: ${file.params.uri}'); - return; - } - } - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.blue, - backgroundColor: Colors.white, - ), - child: const Text('Open File'), - onPressed: () => _openFile(context), - ), - ], - ), - ), - ); - } -} - -/// Widget that displays a text file in a dialog. -class TextDisplay extends StatelessWidget { - /// Default Constructor. - const TextDisplay(this.file, {super.key}); - - /// The file. - final IOSXFile file; - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Text(file.params.uri), - content: Scrollbar( - child: SingleChildScrollView( - child: FutureBuilder( - future: file.readAsString(), - builder: (_, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!); - } else { - return const CircularProgressIndicator(); - } - }, - ), - ), - ), - actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), - ], - ); - } -} diff --git a/packages/cross_file/cross_file_ios/example/pubspec.yaml b/packages/cross_file/cross_file_ios/example/pubspec.yaml deleted file mode 100644 index 92583c1c9d25..000000000000 --- a/packages/cross_file/cross_file_ios/example/pubspec.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: cross_file_ios_example -description: "Demonstrates how to use the cross_file_darwin plugin." -publish_to: 'none' - -environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" - -dependencies: - cross_file_ios: - # When depending on this package from a real application you should use: - # cross_file_darwin: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ - cupertino_icons: ^1.0.8 - file_selector_ios: - path: ../../../file_selector/file_selector_ios - flutter: - sdk: flutter - mime: ^2.0.0 - video_player: ^2.8.6 - -dev_dependencies: - flutter_test: - sdk: flutter - integration_test: - sdk: flutter - -flutter: - uses-material-design: true diff --git a/packages/cross_file/cross_file_ios/example/test/widget_test.dart b/packages/cross_file/cross_file_ios/example/test/widget_test.dart deleted file mode 100644 index 0dfc28c4f8f3..000000000000 --- a/packages/cross_file/cross_file_ios/example/test/widget_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:cross_file_ios_example/main.dart'; - -void main() { - testWidgets('Verify Platform version', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that platform version is retrieved. - expect( - find.byWidgetPredicate( - (Widget widget) => widget is Text && - widget.data!.startsWith('Running on:'), - ), - findsOneWidget, - ); - }); -} diff --git a/packages/cross_file/cross_file_ios/ios/.gitignore b/packages/cross_file/cross_file_ios/ios/.gitignore deleted file mode 100644 index 034771fc9c9b..000000000000 --- a/packages/cross_file/cross_file_ios/ios/.gitignore +++ /dev/null @@ -1,38 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig -/Flutter/ephemeral/ -/Flutter/flutter_export_environment.sh diff --git a/packages/cross_file/cross_file_ios/ios/Assets/.gitkeep b/packages/cross_file/cross_file_ios/ios/Assets/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift b/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift deleted file mode 100644 index 50a22460adf0..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/CrossFileIOSPlugin.swift +++ /dev/null @@ -1,23 +0,0 @@ -import Flutter -import UIKit - -public class CrossFileIOSPlugin: NSObject, FlutterPlugin { - var proxyApiRegistrar: FoundationPigeonProxyApiRegistrar? - - init(binaryMessenger: FlutterBinaryMessenger) { - proxyApiRegistrar = FoundationPigeonProxyApiRegistrar( - binaryMessenger: binaryMessenger, apiDelegate: ProxyApiDelegate()) - proxyApiRegistrar?.setUp() - } - - public static func register(with registrar: FlutterPluginRegistrar) { - let plugin = CrossFileIOSPlugin(binaryMessenger: registrar.messenger()) - registrar.publish(plugin) - } - - public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - proxyApiRegistrar!.ignoreCallsToDart = true - proxyApiRegistrar!.tearDown() - proxyApiRegistrar = nil - } -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift deleted file mode 100644 index 4cedb4f39948..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/ProxyAPIDelegate.swift +++ /dev/null @@ -1,33 +0,0 @@ -import Foundation - -/// Implementation of `FoundationPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation -/// and any additional resources needed by an implementation. -open class ProxyApiDelegate: FoundationPigeonProxyApiDelegate { - /// Creates an error when the constructor of a class returns null. - func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { - return PigeonError( - code: "ConstructorReturnedNullError", - message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", - details: nil) - } - - func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL { - return PigeonApiURL(pigeonRegistrar: registrar, delegate: URLProxyAPIDelegate()) - } - - func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle { - return PigeonApiFileHandle(pigeonRegistrar: registrar, delegate: FileHandleProxyAPIDelegate()) - } - - func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) - -> PigeonApiURLResolvingBookmarkDataResponse - { - return PigeonApiURLResolvingBookmarkDataResponse( - pigeonRegistrar: registrar, delegate: URLResolvingBookmarkDataResponseProxyAPIDelegate()) - } - - func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager - { - return PigeonApiFileManager(pigeonRegistrar: registrar, delegate: FileManagerProxyAPIDelegate()) - } -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift b/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift deleted file mode 100644 index 29c3b47163b7..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/URLResolvingBookmarkDataResponse.swift +++ /dev/null @@ -1,9 +0,0 @@ -class URLResolvingBookmarkDataResponse { - let url: URL - let isStale: Bool - - init(url: URL, isStale: Bool) { - self.url = url - self.isStale = isStale - } -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift deleted file mode 100644 index e2942a2231c1..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileHandleProxyAPIDelegate.swift +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import Foundation - -/// ProxyApi implementation for `FileHandle`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle { - return try FileHandle(forReadingFrom: url) - } - - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws - -> FlutterStandardTypedData? - { - var bytes: Data? - if #available(iOS 13.4, *) { - bytes = try pigeonInstance.readToEnd() - } else { - bytes = pigeonInstance.readDataToEndOfFile() - } - - if let bytes = bytes { - return FlutterStandardTypedData(bytes: bytes) - } - - return nil - } - - func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { - try pigeonInstance.close() - } - - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) - throws -> FlutterStandardTypedData? - { - if #available(iOS 13.4, *) { - let data = try pigeonInstance.read(upToCount: Int(count)) - if let data = data { - return FlutterStandardTypedData(bytes: data) - } - } - - return nil - } -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift deleted file mode 100644 index 5ed645924158..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/FileManagerProxyAPIDelegate.swift +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - -/// ProxyApi implementation for `FileManager`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class FileManagerProxyAPIDelegate: PigeonApiDelegateFileManager { - func defaultManager(pigeonApi: PigeonApiFileManager) -> FileManager { - return FileManager.default - } - - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) - throws -> Bool - { - return pigeonInstance.fileExists(atPath: atPath) - } - - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) - throws -> Bool - { - return pigeonInstance.isReadableFile(atPath: atPath) - } - - func fileModificationDate( - pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String - ) throws -> Int64? { - let attributes: NSDictionary = - try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary - if let date = attributes.fileModificationDate() { - return Int64(date.timeIntervalSince1970 * 1000) - } - - return nil - } - - func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws - -> Int64? - { - let attributes: NSDictionary = - try pigeonInstance.attributesOfItem(atPath: atPath) as NSDictionary - return Int64(attributes.fileSize()) - } -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift deleted file mode 100644 index 523feb6d73a7..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/Foundation.g.swift +++ /dev/null @@ -1,1611 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Sendable? - - init(code: String, message: String?, details: Sendable?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError( - code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", - details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -/// Handles the callback when an object is deallocated. -protocol FoundationPigeonInternalFinalizerDelegate: AnyObject { - /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. - func onDeinit(identifier: Int64) -} - -// Attaches to an object to receive a callback when the object is deallocated. -internal final class FoundationPigeonInternalFinalizer { - internal static let associatedObjectKey = malloc(1)! - - private let identifier: Int64 - // Reference to the delegate is weak because the callback should be ignored if the - // `InstanceManager` is deallocated. - internal weak var delegate: FoundationPigeonInternalFinalizerDelegate? - - private init(identifier: Int64, delegate: FoundationPigeonInternalFinalizerDelegate) { - self.identifier = identifier - self.delegate = delegate - } - - internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: FoundationPigeonInternalFinalizerDelegate - ) { - let finalizer = FoundationPigeonInternalFinalizer(identifier: identifier, delegate: delegate) - objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) - } - - static func detach(from instance: AnyObject) { - let finalizer = - objc_getAssociatedObject(instance, associatedObjectKey) as? FoundationPigeonInternalFinalizer - if let finalizer = finalizer { - finalizer.delegate = nil - objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) - } - } - - deinit { - delegate?.onDeinit(identifier: identifier) - } -} - -/// Maintains instances used to communicate with the corresponding objects in Dart. -/// -/// Objects stored in this container are represented by an object in Dart that is also stored in -/// an InstanceManager with the same identifier. -/// -/// When an instance is added with an identifier, either can be used to retrieve the other. -/// -/// Added instances are added as a weak reference and a strong reference. When the strong -/// reference is removed and the weak reference is deallocated,`FoundationPigeonInternalFinalizerDelegate.onDeinit` -/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is -/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), -/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually -/// again. -/// -/// Accessing and inserting to an InstanceManager is thread safe. -final class FoundationPigeonInstanceManager { - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously from Dart. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - private static let minHostCreatedIdentifier: Int64 = 65536 - - private let lockQueue = DispatchQueue(label: "FoundationPigeonInstanceManager") - private let identifiers: NSMapTable = NSMapTable( - keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) - private let weakInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) - private let strongInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) - private let finalizerDelegate: FoundationPigeonInternalFinalizerDelegate - private var nextIdentifier: Int64 = minHostCreatedIdentifier - - public init(finalizerDelegate: FoundationPigeonInternalFinalizerDelegate) { - self.finalizerDelegate = finalizerDelegate - } - - /// Adds a new instance that was instantiated from Dart. - /// - /// The same instance can be added multiple times, but each identifier must be unique. This allows - /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. - /// - /// - Parameters: - /// - instance: the instance to be stored - /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique - func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - lockQueue.async { - self.addInstance(instance, withIdentifier: identifier) - } - } - - /// Adds a new instance that was instantiated from the host platform. - /// - /// - Parameters: - /// - instance: the instance to be stored. This must be unique to all other added instances. - /// - Returns: the unique identifier (>= 0) stored with instance - func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { - assert(!containsInstance(instance), "Instance of \(instance) has already been added.") - var identifier: Int64 = -1 - lockQueue.sync { - identifier = nextIdentifier - nextIdentifier += 1 - self.addInstance(instance, withIdentifier: identifier) - } - return identifier - } - - /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier paired to an instance. - /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if - /// the manager doesn't contain the value - func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) - strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - /// Retrieves the instance associated with identifier. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier associated with an instance - /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func instance(forIdentifier instanceIdentifier: Int64) -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - assert(identifier >= 0) - assert( - weakInstances.object(forKey: identifier as NSNumber) == nil, - "Identifier has already been added: \(identifier)") - identifiers.setObject(NSNumber(value: identifier), forKey: instance) - weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) - strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - FoundationPigeonInternalFinalizer.attach( - to: instance, identifier: identifier, delegate: finalizerDelegate) - } - - /// Retrieves the identifier paired with an instance. - /// - /// If the manager contains a strong reference to `instance`, it will return the identifier - /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new - /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. - /// - /// If this method returns a nonnull identifier, this method also expects the Dart - /// `FoundationPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - /// identifier is associated with. - /// - /// - Parameters: - /// - instance: an instance that may be stored in the manager - /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { - var identifier: Int64? = nil - lockQueue.sync { - if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { - strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) - identifier = existingIdentifier - } - } - return identifier - } - - /// Whether this manager contains the given `instance`. - /// - /// - Parameters: - /// - instance: the instance whose presence in this manager is to be tested - /// - Returns: whether this manager contains the given `instance` - func containsInstance(_ instance: AnyObject) -> Bool { - var containsInstance = false - lockQueue.sync { - containsInstance = identifiers.object(forKey: instance) != nil - } - return containsInstance - } - - /// Removes all of the instances from this manager. - /// - /// The manager will be empty after this call returns. - func removeAllObjects() throws { - lockQueue.sync { - let weakInstancesEnumerator = weakInstances.objectEnumerator()! - while let instance = weakInstancesEnumerator.nextObject() { - FoundationPigeonInternalFinalizer.detach(from: instance as AnyObject) - } - identifiers.removeAllObjects() - weakInstances.removeAllObjects() - strongInstances.removeAllObjects() - nextIdentifier = FoundationPigeonInstanceManager.minHostCreatedIdentifier - } - } - - /// The number of instances stored as a strong reference. - /// - /// For debugging and testing purposes. - internal var strongInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = strongInstances.count - } - return count - } - - /// The number of instances stored as a weak reference. - /// - /// For debugging and testing purposes. NSMapTables that store keys or objects as weak - /// reference will be reclaimed non-deterministically. - internal var weakInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = weakInstances.count - } - return count - } -} - -private class FoundationPigeonInstanceManagerApi { - /// The codec used for serializing messages. - var codec: FlutterStandardMessageCodec { FoundationPigeonCodec.shared } - - /// Handles sending and receiving messages with Dart. - unowned let binaryMessenger: FlutterBinaryMessenger - - init(binaryMessenger: FlutterBinaryMessenger) { - self.binaryMessenger = binaryMessenger - } - - /// Sets up an instance of `FoundationPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, instanceManager: FoundationPigeonInstanceManager? - ) { - let codec = FoundationPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference", - binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - removeStrongReferenceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! Int64 - do { - let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - removeStrongReferenceChannel.setMessageHandler(nil) - } - let clearChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.clear", - binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - clearChannel.setMessageHandler { _, reply in - do { - try instanceManager.removeAllObjects() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - clearChannel.setMessageHandler(nil) - } - } - - /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference( - identifier identifierArg: Int64, completion: @escaping (Result) -> Void - ) { - let channelName: String = - "dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([identifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } -} -protocol FoundationPigeonProxyApiDelegate { - /// An implementation of [PigeonApiURLResolvingBookmarkDataResponse] used to add a new Dart instance of - /// `URLResolvingBookmarkDataResponse` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiURLResolvingBookmarkDataResponse(_ registrar: FoundationPigeonProxyApiRegistrar) - -> PigeonApiURLResolvingBookmarkDataResponse - /// An implementation of [PigeonApiURL] used to add a new Dart instance of - /// `URL` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiURL(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiURL - /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of - /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileHandle - /// An implementation of [PigeonApiFileManager] used to add a new Dart instance of - /// `FileManager` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileManager(_ registrar: FoundationPigeonProxyApiRegistrar) -> PigeonApiFileManager -} - -open class FoundationPigeonProxyApiRegistrar { - let binaryMessenger: FlutterBinaryMessenger - let apiDelegate: FoundationPigeonProxyApiDelegate - let instanceManager: FoundationPigeonInstanceManager - /// Whether APIs should ignore calling to Dart. - public var ignoreCallsToDart = false - private var _codec: FlutterStandardMessageCodec? - var codec: FlutterStandardMessageCodec { - if _codec == nil { - _codec = FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) - } - return _codec! - } - - private class InstanceManagerApiFinalizerDelegate: FoundationPigeonInternalFinalizerDelegate { - let api: FoundationPigeonInstanceManagerApi - - init(_ api: FoundationPigeonInstanceManagerApi) { - self.api = api - } - - public func onDeinit(identifier: Int64) { - api.removeStrongReference(identifier: identifier) { - _ in - } - } - } - - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: FoundationPigeonProxyApiDelegate) { - self.binaryMessenger = binaryMessenger - self.apiDelegate = apiDelegate - self.instanceManager = FoundationPigeonInstanceManager( - finalizerDelegate: InstanceManagerApiFinalizerDelegate( - FoundationPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) - } - - func setUp() { - FoundationPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiURL.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiURL(self)) - PigeonApiFileHandle.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) - PigeonApiFileManager.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileManager(self)) - } - func tearDown() { - FoundationPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: nil) - PigeonApiURL.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - PigeonApiFileManager.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - } -} -private class FoundationPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - - private class FoundationPigeonInternalProxyApiCodecReader: FoundationPigeonCodecReader { - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - - init(data: Data, pigeonRegistrar: FoundationPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 128: - let identifier = self.readValue() - let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( - forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) - if instance == nil { - print("Failed to find instance with identifier: \(identifier!)") - } - return instance - default: - return super.readValue(ofType: type) - } - } - } - - private class FoundationPigeonInternalProxyApiCodecWriter: FoundationPigeonCodecWriter { - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - - init(data: NSMutableData, pigeonRegistrar: FoundationPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] - || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String - || value is URLBookmarkCreationOptions || value is URLResourceKeyEnum - || value is URLBookmarkResolutionOptions - { - super.writeValue(value) - return - } - - if let instance = value as? URLResolvingBookmarkDataResponse { - pigeonRegistrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(pigeonRegistrar) - .pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) - return - } - - if let instance = value as? URL { - pigeonRegistrar.apiDelegate.pigeonApiURL(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) - return - } - - if let instance = value as? FileHandle { - pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) - return - } - - if let instance = value as? FileManager { - pigeonRegistrar.apiDelegate.pigeonApiFileManager(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) - return - } - - if let instance = value as AnyObject?, - pigeonRegistrar.instanceManager.containsInstance(instance) - { - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) - } else { - print("Unsupported value: \(value) of \(type(of: value))") - assert(false, "Unsupported value for FoundationPigeonInternalProxyApiCodecWriter") - } - - } - } - - init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - } - - override func reader(with data: Data) -> FlutterStandardReader { - return FoundationPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return FoundationPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) - } -} - -enum URLBookmarkCreationOptions: Int { - case minimalBookmark = 0 - case suitableForBookmarkOptions = 1 -} - -enum URLResourceKeyEnum: Int { - case isDirectoryKey = 0 - case parentDirectoryURLKey = 1 -} - -enum URLBookmarkResolutionOptions: Int { - case withoutUI = 0 - case withoutMounting = 1 -} - -private class FoundationPigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) - if let enumResultAsInt = enumResultAsInt { - return URLBookmarkCreationOptions(rawValue: enumResultAsInt) - } - return nil - case 130: - let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) - if let enumResultAsInt = enumResultAsInt { - return URLResourceKeyEnum(rawValue: enumResultAsInt) - } - return nil - case 131: - let enumResultAsInt: Int? = nilOrValue(self.readValue() as! Int?) - if let enumResultAsInt = enumResultAsInt { - return URLBookmarkResolutionOptions(rawValue: enumResultAsInt) - } - return nil - default: - return super.readValue(ofType: type) - } - } -} - -private class FoundationPigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? URLBookmarkCreationOptions { - super.writeByte(129) - super.writeValue(value.rawValue) - } else if let value = value as? URLResourceKeyEnum { - super.writeByte(130) - super.writeValue(value.rawValue) - } else if let value = value as? URLBookmarkResolutionOptions { - super.writeByte(131) - super.writeValue(value.rawValue) - } else { - super.writeValue(value) - } - } -} - -private class FoundationPigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return FoundationPigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return FoundationPigeonCodecWriter(data: data) - } -} - -class FoundationPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = FoundationPigeonCodec(readerWriter: FoundationPigeonCodecReaderWriter()) -} - -protocol PigeonApiDelegateURLResolvingBookmarkDataResponse { - func url( - pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, - pigeonInstance: URLResolvingBookmarkDataResponse - ) throws -> URL - func isStale( - pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, - pigeonInstance: URLResolvingBookmarkDataResponse - ) throws -> Bool -} - -protocol PigeonApiProtocolURLResolvingBookmarkDataResponse { -} - -final class PigeonApiURLResolvingBookmarkDataResponse: - PigeonApiProtocolURLResolvingBookmarkDataResponse -{ - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateURLResolvingBookmarkDataResponse - init( - pigeonRegistrar: FoundationPigeonProxyApiRegistrar, - delegate: PigeonApiDelegateURLResolvingBookmarkDataResponse - ) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - ///Creates a Dart instance of URLResolvingBookmarkDataResponse and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: URLResolvingBookmarkDataResponse, - completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( - pigeonInstance as AnyObject) - let urlArg = try! pigeonDelegate.url(pigeonApi: self, pigeonInstance: pigeonInstance) - let isStaleArg = try! pigeonDelegate.isStale(pigeonApi: self, pigeonInstance: pigeonInstance) - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = - "dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonIdentifierArg, urlArg, isStaleArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - - - -/// ProxyApi implementation for `URLResolvingBookmarkDataResponse`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class URLResolvingBookmarkDataResponseProxyAPIDelegate : PigeonApiDelegateURLResolvingBookmarkDataResponse { - func url(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> URL { - return pigeonInstance.url - } - - func isStale(pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, pigeonInstance: URLResolvingBookmarkDataResponse) throws -> Bool { - return pigeonInstance.isStale - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -import Flutter -import XCTest - -@testable import cross_file_ios - -class URLResolvingBookmarkDataResponseTests: XCTestCase { - func testUrl() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) - - let instance = TestURLResolvingBookmarkDataResponse() - let value = try? api.pigeonDelegate.url(pigeonApi: api, pigeonInstance: instance) - - XCTAssertEqual(value, instance.url) - } - - func testIsStale() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURLResolvingBookmarkDataResponse(registrar) - - let instance = TestURLResolvingBookmarkDataResponse() - let value = try? api.pigeonDelegate.isStale(pigeonApi: api, pigeonInstance: instance) - - XCTAssertEqual(value, instance.isStale) - } - -} -*/ - -protocol PigeonApiDelegateURL { - func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? - func resolvingBookmarkData( - pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, - options: [URLBookmarkResolutionOptions], relativeTo: URL? - ) throws -> URLResolvingBookmarkDataResponse - func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String - func bookmarkData( - pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], - keys: [URLResourceKeyEnum]?, relativeTo: URL? - ) throws -> FlutterStandardTypedData - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws - -> Bool - func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -} - -protocol PigeonApiProtocolURL { -} - -final class PigeonApiURL: PigeonApiProtocolURL { - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateURL - init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateURL) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiURL?) { - let codec: FlutterStandardMessageCodec = - api != nil - ? FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) - : FlutterStandardMessageCodec.sharedInstance() - let fileURLWithPathChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.URL.fileURLWithPath", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileURLWithPathChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pathArg = args[0] as! String - do { - let result = try api.pigeonDelegate.fileURLWithPath(pigeonApi: api, path: pathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileURLWithPathChannel.setMessageHandler(nil) - } - let resolvingBookmarkDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.URL.resolvingBookmarkData", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - resolvingBookmarkDataChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let dataArg = args[0] as! FlutterStandardTypedData - let optionsArg = args[1] as! [URLBookmarkResolutionOptions] - let relativeToArg: URL? = nilOrValue(args[2]) - do { - let result = try api.pigeonDelegate.resolvingBookmarkData( - pigeonApi: api, data: dataArg, options: optionsArg, relativeTo: relativeToArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - resolvingBookmarkDataChannel.setMessageHandler(nil) - } - let pathChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.URL.path", binaryMessenger: binaryMessenger, - codec: codec) - if let api = api { - pathChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! URL - do { - let result = try api.pigeonDelegate.path( - pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - pathChannel.setMessageHandler(nil) - } - let bookmarkDataChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.URL.bookmarkData", binaryMessenger: binaryMessenger, - codec: codec) - if let api = api { - bookmarkDataChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! URL - let optionsArg = args[1] as! [URLBookmarkCreationOptions] - let keysArg: [URLResourceKeyEnum]? = nilOrValue(args[2]) - let relativeToArg: URL? = nilOrValue(args[3]) - do { - let result = try api.pigeonDelegate.bookmarkData( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, options: optionsArg, keys: keysArg, - relativeTo: relativeToArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - bookmarkDataChannel.setMessageHandler(nil) - } - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! URL - do { - let result = try api.pigeonDelegate.startAccessingSecurityScopedResource( - pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) - } - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! URL - do { - try api.pigeonDelegate.stopAccessingSecurityScopedResource( - pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) - } - } - - ///Creates a Dart instance of URL and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: URL, completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( - pigeonInstance as AnyObject) - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - - - -/// ProxyApi implementation for `URL`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class URLProxyAPIDelegate : PigeonApiDelegateURL { - func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? { - return URL.fileURLWithPath(path: path) - } - - func resolvingBookmarkData(pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, options: [URLBookmarkResolutionOptions], relativeTo: URL?) throws -> URLResolvingBookmarkDataResponse { - return URL.resolvingBookmarkData(data: data, options: options, relativeTo: relativeTo) - } - - func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String { - return pigeonInstance.path() - } - - func bookmarkData(pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], keys: [URLResourceKeyEnum]?, relativeTo: URL?) throws -> FlutterStandardTypedData { - return pigeonInstance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo) - } - - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> Bool { - return pigeonInstance.startAccessingSecurityScopedResource() - } - - func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws { - pigeonInstance.stopAccessingSecurityScopedResource() - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -import Flutter -import XCTest - -@testable import cross_file_ios - -class URLTests: XCTestCase { - func testPath() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - let value = try? api.pigeonDelegate.path(pigeonApi: api, pigeonInstance: instance ) - - XCTAssertTrue(instance.pathCalled) - XCTAssertEqual(value, instance.path()) - } - - func testBookmarkData() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - let options = [.minimalBookmark] - let keys = [.isDirectoryKey] - let relativeTo = TestURL - let value = try? api.pigeonDelegate.bookmarkData(pigeonApi: api, pigeonInstance: instance, options: options, keys: keys, relativeTo: relativeTo) - - XCTAssertEqual(instance.bookmarkDataArgs, [options, keys, relativeTo]) - XCTAssertEqual(value, instance.bookmarkData(options: options, keys: keys, relativeTo: relativeTo)) - } - - func testStartAccessingSecurityScopedResource() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - let value = try? api.pigeonDelegate.startAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) - - XCTAssertTrue(instance.startAccessingSecurityScopedResourceCalled) - XCTAssertEqual(value, instance.startAccessingSecurityScopedResource()) - } - - func testStopAccessingSecurityScopedResource() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiURL(registrar) - - let instance = TestURL() - try? api.pigeonDelegate.stopAccessingSecurityScopedResource(pigeonApi: api, pigeonInstance: instance ) - - XCTAssertTrue(instance.stopAccessingSecurityScopedResourceCalled) - } - -} -class TestURL: URL { - var pathCalled = false - var bookmarkDataArgs: [AnyHashable?]? = nil - var startAccessingSecurityScopedResourceCalled = false - var stopAccessingSecurityScopedResourceCalled = false - - - override func path() { - pathCalled = true - } - override func bookmarkData() { - bookmarkDataArgs = [options, keys, relativeTo] - return byteArrayOf(0xA1.toByte()) - } - override func startAccessingSecurityScopedResource() { - startAccessingSecurityScopedResourceCalled = true - } - override func stopAccessingSecurityScopedResource() { - stopAccessingSecurityScopedResourceCalled = true - } -} -*/ - -protocol PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) - throws -> FlutterStandardTypedData? - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws - -> FlutterStandardTypedData? - func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -} - -protocol PigeonApiProtocolFileHandle { -} - -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateFileHandle - init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle? - ) { - let codec: FlutterStandardMessageCodec = - api != nil - ? FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) - : FlutterStandardMessageCodec.sharedInstance() - let forReadingFromUrlChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileHandle.forReadingFromUrl", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - forReadingFromUrlChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonIdentifierArg = args[0] as! Int64 - let urlArg = args[1] as! URL - do { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - try api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: urlArg), - withIdentifier: pigeonIdentifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - forReadingFromUrlChannel.setMessageHandler(nil) - } - let readUpToCountChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readUpToCount", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readUpToCountChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - let countArg = args[1] as! Int64 - do { - let result = try api.pigeonDelegate.readUpToCount( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - readUpToCountChannel.setMessageHandler(nil) - } - let readToEndChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readToEndChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - do { - let result = try api.pigeonDelegate.readToEnd( - pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - readToEndChannel.setMessageHandler(nil) - } - let closeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileHandle.close", binaryMessenger: binaryMessenger, - codec: codec) - if let api = api { - closeChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - do { - try api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - closeChannel.setMessageHandler(nil) - } - } - - ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: FileHandle, completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( - pigeonInstance as AnyObject) - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - - - -/// ProxyApi implementation for `FileHandle`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class FileHandleProxyAPIDelegate : PigeonApiDelegateFileHandle { - func forReadingFromUrl(pigeonApi: PigeonApiFileHandle, url: URL) throws -> FileHandle { - return FileHandle(,url: url) - } - - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? { - return pigeonInstance.readUpToCount(count: count) - } - - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? { - return pigeonInstance.readToEnd() - } - - func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { - pigeonInstance.close() - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -import Flutter -import XCTest - -@testable import cross_file_ios - -class FileHandleTests: XCTestCase { - func testForReadingFromUrl() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = try? api.pigeonDelegate.forReadingFromUrl(pigeonApi: api, url: TestURL) - XCTAssertNotNil(instance) - } - - func testReadUpToCount() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - let count = 0 - let value = try? api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: instance, count: count) - - XCTAssertEqual(instance.readUpToCountArgs, [count]) - XCTAssertEqual(value, instance.readUpToCount(count: count)) - } - - func testReadToEnd() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance ) - - XCTAssertTrue(instance.readToEndCalled) - XCTAssertEqual(value, instance.readToEnd()) - } - - func testClose() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let instance = TestFileHandle() - try? api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: instance ) - - XCTAssertTrue(instance.closeCalled) - } - -} -class TestFileHandle: FileHandle { - var readUpToCountArgs: [AnyHashable?]? = nil - var readToEndCalled = false - var closeCalled = false - - - override func readUpToCount() { - readUpToCountArgs = [count] - return byteArrayOf(0xA1.toByte()) - } - override func readToEnd() { - readToEndCalled = true - } - override func close() { - closeCalled = true - } -} -*/ - -protocol PigeonApiDelegateFileManager { - func defaultManager(pigeonApi: PigeonApiFileManager) throws -> FileManager - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) - throws -> Bool - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) - throws -> Bool - func fileModificationDate( - pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String - ) throws -> Int64? - func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws - -> Int64? -} - -protocol PigeonApiProtocolFileManager { -} - -final class PigeonApiFileManager: PigeonApiProtocolFileManager { - unowned let pigeonRegistrar: FoundationPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateFileManager - init(pigeonRegistrar: FoundationPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileManager) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileManager? - ) { - let codec: FlutterStandardMessageCodec = - api != nil - ? FlutterStandardMessageCodec( - readerWriter: FoundationPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) - : FlutterStandardMessageCodec.sharedInstance() - let defaultManagerChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - defaultManagerChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonIdentifierArg = args[0] as! Int64 - do { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - try api.pigeonDelegate.defaultManager(pigeonApi: api), - withIdentifier: pigeonIdentifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - defaultManagerChannel.setMessageHandler(nil) - } - let fileExistsChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileExists", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileExistsChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String - do { - let result = try api.pigeonDelegate.fileExists( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileExistsChannel.setMessageHandler(nil) - } - let isReadableFileChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isReadableFileChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String - do { - let result = try api.pigeonDelegate.isReadableFile( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isReadableFileChannel.setMessageHandler(nil) - } - let fileModificationDateChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileModificationDate", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileModificationDateChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String - do { - let result = try api.pigeonDelegate.fileModificationDate( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileModificationDateChannel.setMessageHandler(nil) - } - let fileSizeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_ios.FileManager.fileSize", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileSizeChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileManager - let atPathArg = args[1] as! String - do { - let result = try api.pigeonDelegate.fileSize( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, atPath: atPathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileSizeChannel.setMessageHandler(nil) - } - } - - ///Creates a Dart instance of FileManager and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: FileManager, completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( - pigeonInstance as AnyObject) - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - } -} - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - - - -/// ProxyApi implementation for `FileManager`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class FileManagerProxyAPIDelegate : PigeonApiDelegateFileManager { - func defaultManager(pigeonApi: PigeonApiFileManager): FileManager { - return FileManager.defaultManager - } - - func fileExists(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { - return pigeonInstance.fileExists(atPath: atPath) - } - - func isReadableFile(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Bool { - return pigeonInstance.isReadableFile(atPath: atPath) - } - - func fileModificationDate(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { - return pigeonInstance.fileModificationDate(atPath: atPath) - } - - func fileSize(pigeonApi: PigeonApiFileManager, pigeonInstance: FileManager, atPath: String) throws -> Int64? { - return pigeonInstance.fileSize(atPath: atPath) - } - -} -*/ - -/* -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -import Flutter -import XCTest - -@testable import cross_file_ios - -class FileManagerTests: XCTestCase { - func testFileExists() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.fileExists(pigeonApi: api, pigeonInstance: instance, atPath: atPath) - - XCTAssertEqual(instance.fileExistsArgs, [atPath]) - XCTAssertEqual(value, instance.fileExists(atPath: atPath)) - } - - func testIsReadableFile() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.isReadableFile(pigeonApi: api, pigeonInstance: instance, atPath: atPath) - - XCTAssertEqual(instance.isReadableFileArgs, [atPath]) - XCTAssertEqual(value, instance.isReadableFile(atPath: atPath)) - } - - func testFileModificationDate() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.fileModificationDate(pigeonApi: api, pigeonInstance: instance, atPath: atPath) - - XCTAssertEqual(instance.fileModificationDateArgs, [atPath]) - XCTAssertEqual(value, instance.fileModificationDate(atPath: atPath)) - } - - func testFileSize() { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiFileManager(registrar) - - let instance = TestFileManager() - let atPath = "myString" - let value = try? api.pigeonDelegate.fileSize(pigeonApi: api, pigeonInstance: instance, atPath: atPath) - - XCTAssertEqual(instance.fileSizeArgs, [atPath]) - XCTAssertEqual(value, instance.fileSize(atPath: atPath)) - } - -} -class TestFileManager: FileManager { - var fileExistsArgs: [AnyHashable?]? = nil - var isReadableFileArgs: [AnyHashable?]? = nil - var fileModificationDateArgs: [AnyHashable?]? = nil - var fileSizeArgs: [AnyHashable?]? = nil - - - override func fileExists() { - fileExistsArgs = [atPath] - return true - } - override func isReadableFile() { - isReadableFileArgs = [atPath] - return true - } - override func fileModificationDate() { - fileModificationDateArgs = [atPath] - return 0 - } - override func fileSize() { - fileSizeArgs = [atPath] - return 0 - } -} -*/ diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift deleted file mode 100644 index fafcc59dcea6..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLProxyAPIDelegate.swift +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import Foundation - -/// ProxyApi implementation for `URL`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class URLProxyAPIDelegate: PigeonApiDelegateURL { - func fileURLWithPath(pigeonApi: PigeonApiURL, path: String) throws -> URL? { - return URL(fileURLWithPath: path) - } - - func resolvingBookmarkData( - pigeonApi: PigeonApiURL, data: FlutterStandardTypedData, - options: [URLBookmarkResolutionOptions], relativeTo: URL? - ) throws -> URLResolvingBookmarkDataResponse { - var isStale: Bool = true - let url: URL = try URL(resolvingBookmarkData: data.data, bookmarkDataIsStale: &isStale) - return URLResolvingBookmarkDataResponse(url: url, isStale: isStale) - } - - func path(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws -> String { - return pigeonInstance.path - } - - func bookmarkData( - pigeonApi: PigeonApiURL, pigeonInstance: URL, options: [URLBookmarkCreationOptions], - keys: [URLResourceKeyEnum]?, relativeTo: URL? - ) throws -> FlutterStandardTypedData { - let data = try pigeonInstance.bookmarkData( - options: [], - includingResourceValuesForKeys: nil, - relativeTo: relativeTo - ) - - return FlutterStandardTypedData(bytes: data) - } - - func startAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws - -> Bool - { - return pigeonInstance.startAccessingSecurityScopedResource() - } - - func stopAccessingSecurityScopedResource(pigeonApi: PigeonApiURL, pigeonInstance: URL) throws { - pigeonInstance.stopAccessingSecurityScopedResource() - } - -} diff --git a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift b/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift deleted file mode 100644 index 6b455e816efa..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Classes/proxies/URLResolvingBookmarkDataResponseProxyAPIDelegate.swift +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - -/// ProxyApi implementation for `URLResolvingBookmarkDataResponse`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class URLResolvingBookmarkDataResponseProxyAPIDelegate: - PigeonApiDelegateURLResolvingBookmarkDataResponse -{ - func url( - pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, - pigeonInstance: URLResolvingBookmarkDataResponse - ) throws -> URL { - return pigeonInstance.url - } - - func isStale( - pigeonApi: PigeonApiURLResolvingBookmarkDataResponse, - pigeonInstance: URLResolvingBookmarkDataResponse - ) throws -> Bool { - return pigeonInstance.isStale - } - -} diff --git a/packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy b/packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy deleted file mode 100644 index a34b7e2e60cc..000000000000 --- a/packages/cross_file/cross_file_ios/ios/Resources/PrivacyInfo.xcprivacy +++ /dev/null @@ -1,14 +0,0 @@ - - - - - NSPrivacyTrackingDomains - - NSPrivacyAccessedAPITypes - - NSPrivacyCollectedDataTypes - - NSPrivacyTracking - - - diff --git a/packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec b/packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec deleted file mode 100644 index c009200d1815..000000000000 --- a/packages/cross_file/cross_file_ios/ios/cross_file_ios.podspec +++ /dev/null @@ -1,29 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint cross_file_ios.podspec` to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'cross_file_ios' - s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' - s.description = <<-DESC -A new Flutter plugin project. - DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.dependency 'Flutter' - s.platform = :ios, '13.0' - - # Flutter.framework does not contain a i386 slice. - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } - s.swift_version = '5.0' - - # If your plugin requires a privacy manifest, for example if it uses any - # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your - # plugin's privacy impact, and then uncomment this line. For more information, - # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - # s.resource_bundles = {'cross_file_ios_privacy' => ['Resources/PrivacyInfo.xcprivacy']} -end diff --git a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart deleted file mode 100644 index b30dfb339087..000000000000 --- a/packages/cross_file/cross_file_ios/lib/cross_file_ios.dart +++ /dev/null @@ -1,4 +0,0 @@ -export 'src/ios_cross_file.dart'; -export 'src/cross_file_ios.dart'; -export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show PlatformScopedStorageXFileCreationParams; diff --git a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart b/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart deleted file mode 100644 index f9a0486c7d27..000000000000 --- a/packages/cross_file/cross_file_ios/lib/src/cross_file_ios.dart +++ /dev/null @@ -1,24 +0,0 @@ -// Platform Implementation for Android -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; - -import 'ios_cross_file.dart'; - -final class CrossFileIOS extends CrossFilePlatform { - static void registerWith() { - CrossFilePlatform.instance = CrossFileIOS(); - } - - @override - IOSXFile createPlatformXFile(PlatformXFileCreationParams params) { - return IOSXFile( - PlatformScopedStorageXFileCreationParams(uri: params.uri), - ); - } - - @override - PlatformScopedStorageXFile createPlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams params, - ) { - return IOSXFile(params); - } -} diff --git a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart b/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart deleted file mode 100644 index d49679c068e1..000000000000 --- a/packages/cross_file/cross_file_ios/lib/src/foundation.g.dart +++ /dev/null @@ -1,1318 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.0), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers - -import 'dart:async'; -import 'dart:io' show Platform; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; - -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; - -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); -} - -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; - } - return [error.code, error.message, error.details]; -} -/// Provides overrides for the constructors and static members of each -/// Dart proxy class. -/// -/// This is only intended to be used with unit tests to prevent errors from -/// making message calls in a unit test. -/// -/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. -@visibleForTesting -class PigeonOverrides { - /// Overrides [FileHandle.forReadingFromUrl]. - static FileHandle Function({required URL url})? fileHandle_forReadingFromUrl; - - /// Overrides [FileManager.defaultManager]. - static FileManager? fileManager_defaultManager; - - /// Overrides [URL.fileURLWithPath]. - static Future Function(String)? uRL_fileURLWithPath; - - /// Overrides [URL.resolvingBookmarkData]. - static Future Function( - Uint8List, - List, - URL?, - )? uRL_resolvingBookmarkData; - - /// Sets all overridden ProxyApi class members to null. - static void pigeon_reset() { - uRL_fileURLWithPath = null; - uRL_resolvingBookmarkData = null; - fileHandle_forReadingFromUrl = null; - fileManager_defaultManager = null; - } -} - -/// An immutable object that serves as the base class for all Dart proxy classes -/// and can provide functional copies of itself. -/// -/// All implementers are expected to be [immutable] as defined by the annotation -/// and override [pigeon_copy] returning an instance of itself. -@immutable -abstract class PigeonInternalProxyApiBaseClass { - /// Construct a [PigeonInternalProxyApiBaseClass]. - PigeonInternalProxyApiBaseClass({ - this.pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; - - /// Sends and receives binary data across the Flutter platform barrier. - /// - /// If it is null, the default BinaryMessenger will be used, which routes to - /// the host platform. - @protected - final BinaryMessenger? pigeon_binaryMessenger; - - /// Maintains instances stored to communicate with native language objects. - final PigeonInstanceManager pigeon_instanceManager; - - /// Instantiates and returns a functionally identical object to oneself. - /// - /// Outside of tests, this method should only ever be called by - /// [PigeonInstanceManager]. - /// - /// Subclasses should always override their parent's implementation of this - /// method. - @protected - PigeonInternalProxyApiBaseClass pigeon_copy(); -} - -/// Maintains instances used to communicate with the native objects they -/// represent. -/// -/// Added instances are stored as weak references and their copies are stored -/// as strong references to maintain access to their variables and callback -/// methods. Both are stored with the same identifier. -/// -/// When a weak referenced instance becomes inaccessible, -/// [onWeakReferenceRemoved] is called with its associated identifier. -/// -/// If an instance is retrieved and has the possibility to be used, -/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference -/// is added as a weak reference with the same identifier. This prevents a -/// scenario where the weak referenced instance was released and then later -/// returned by the host platform. -class PigeonInstanceManager { - /// Constructs a [PigeonInstanceManager]. - PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { - this.onWeakReferenceRemoved = (int identifier) { - _weakInstances.remove(identifier); - onWeakReferenceRemoved(identifier); - }; - _finalizer = Finalizer(this.onWeakReferenceRemoved); - } - - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously by the host platform. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - static const int _maxDartCreatedIdentifier = 65536; - - /// The default [PigeonInstanceManager] used by Dart proxy classes. - /// - /// On creation, this manager makes a call to clear the native - /// InstanceManager. This is to prevent identifier conflicts after a host - /// restart. - static final PigeonInstanceManager instance = _initInstance(); - - // Expando is used because it doesn't prevent its keys from becoming - // inaccessible. This allows the manager to efficiently retrieve an identifier - // of an instance without holding a strong reference to that instance. - // - // It also doesn't use `==` to search for identifiers, which would lead to an - // infinite loop when comparing an object to its copy. (i.e. which was caused - // by calling instanceManager.getIdentifier() inside of `==` while this was a - // HashMap). - final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; - late final Finalizer _finalizer; - int _nextIdentifier = 0; - - /// Called when a weak referenced instance is removed by [removeWeakReference] - /// or becomes inaccessible. - late final void Function(int) onWeakReferenceRemoved; - - static PigeonInstanceManager _initInstance() { - if (Platform.environment['FLUTTER_TEST'] == 'true') { - return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); - } - WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); - // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. - api.clear(); - final PigeonInstanceManager instanceManager = PigeonInstanceManager( - onWeakReferenceRemoved: (int identifier) { - api.removeStrongReference(identifier); - }, - ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - URLResolvingBookmarkDataResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - URL.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - FileManager.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - return instanceManager; - } - - /// Adds a new instance that was instantiated by Dart. - /// - /// In other words, Dart wants to add a new instance that will represent - /// an object that will be instantiated on the host platform. - /// - /// Throws assertion error if the instance has already been added. - /// - /// Returns the randomly generated id of the [instance] added. - int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { - assert(getIdentifier(instance) == null); - - final int identifier = _nextUniqueIdentifier(); - _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); - _finalizer.attach(instance, identifier, detach: instance); - - final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); - _identifiers[copy] = identifier; - _strongInstances[identifier] = copy; - return identifier; - } - - /// Removes the instance, if present, and call [onWeakReferenceRemoved] with - /// its identifier. - /// - /// Returns the identifier associated with the removed instance. Otherwise, - /// `null` if the instance was not found in this manager. - /// - /// This does not remove the strong referenced instance associated with - /// [instance]. This can be done with [remove]. - int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { - final int? identifier = getIdentifier(instance); - if (identifier == null) { - return null; - } - - _identifiers[instance] = null; - _finalizer.detach(instance); - onWeakReferenceRemoved(identifier); - - return identifier; - } - - /// Removes [identifier] and its associated strongly referenced instance, if - /// present, from the manager. - /// - /// Returns the strong referenced instance associated with [identifier] before - /// it was removed. Returns `null` if [identifier] was not associated with - /// any strong reference. - /// - /// Throws an `AssertionError` if the weak referenced instance associated with - /// [identifier] is not removed first. This can be done with - /// [removeWeakReference]. - T? remove(int identifier) { - final T? instance = _weakInstances[identifier]?.target as T?; - assert( - instance == null, - 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', - ); - return _strongInstances.remove(identifier) as T?; - } - - /// Retrieves the instance associated with identifier. - /// - /// The value returned is chosen from the following order: - /// - /// 1. A weakly referenced instance associated with identifier. - /// 2. If the only instance associated with identifier is a strongly - /// referenced instance, a copy of the instance is added as a weak reference - /// with the same identifier. Returning the newly created copy. - /// 3. If no instance is associated with identifier, returns null. - /// - /// This method also expects the host `InstanceManager` to have a strong - /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; - - if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; - if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); - _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); - _finalizer.attach(copy, identifier, detach: copy); - return copy as T; - } - return strongInstance as T?; - } - - return weakInstance as T; - } - - /// Retrieves the identifier associated with instance. - int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { - return _identifiers[instance]; - } - - /// Adds a new instance that was instantiated by the host platform. - /// - /// In other words, the host platform wants to add a new instance that - /// represents an object on the host platform. Stored with [identifier]. - /// - /// Throws assertion error if the instance or its identifier has already been - /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { - assert(!containsIdentifier(identifier)); - assert(getIdentifier(instance) == null); - assert(identifier >= 0); - - _identifiers[instance] = identifier; - _strongInstances[identifier] = instance; - } - - /// Whether this manager contains the given [identifier]. - bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || - _strongInstances.containsKey(identifier); - } - - int _nextUniqueIdentifier() { - late int identifier; - do { - identifier = _nextIdentifier; - _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; - } while (containsIdentifier(identifier)); - return identifier; - } -} - -/// Generated API for managing the Dart and native `PigeonInstanceManager`s. -class _PigeonInternalInstanceManagerApi { - /// Constructor for [_PigeonInternalInstanceManagerApi]. - _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; - - final BinaryMessenger? pigeonVar_binaryMessenger; - - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - static void setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? binaryMessenger, - PigeonInstanceManager? instanceManager, - }) { - { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference was null.'); - final List args = (message as List?)!; - final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); - try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - Future removeStrongReference(int identifier) async { - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.removeStrongReference'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - /// Clear the native `PigeonInstanceManager`. - /// - /// This is typically called after a hot restart. - Future clear() async { - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.PigeonInternalInstanceManager.clear'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } -} - -class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - - -enum URLBookmarkCreationOptions { - minimalBookmark, - suitableForBookmarkOptions, -} - -enum URLResourceKeyEnum { - isDirectoryKey, - parentDirectoryURLKey, -} - -enum URLBookmarkResolutionOptions { - withoutUI, - withoutMounting, -} - - -class _PigeonCodec extends StandardMessageCodec { - const _PigeonCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is int) { - buffer.putUint8(4); - buffer.putInt64(value); - } else if (value is URLBookmarkCreationOptions) { - buffer.putUint8(129); - writeValue(buffer, value.index); - } else if (value is URLResourceKeyEnum) { - buffer.putUint8(130); - writeValue(buffer, value.index); - } else if (value is URLBookmarkResolutionOptions) { - buffer.putUint8(131); - writeValue(buffer, value.index); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 129: - final int? value = readValue(buffer) as int?; - return value == null ? null : URLBookmarkCreationOptions.values[value]; - case 130: - final int? value = readValue(buffer) as int?; - return value == null ? null : URLResourceKeyEnum.values[value]; - case 131: - final int? value = readValue(buffer) as int?; - return value == null ? null : URLBookmarkResolutionOptions.values[value]; - default: - return super.readValueOfType(type, buffer); - } - } -} -class URLResolvingBookmarkDataResponse extends PigeonInternalProxyApiBaseClass { - /// Constructs [URLResolvingBookmarkDataResponse] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - URLResolvingBookmarkDataResponse.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - required this.url, - required this.isStale, - }); - - final URL url; - - final bool isStale; - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - URLResolvingBookmarkDataResponse Function( - URL url, - bool isStale, - )? pigeon_newInstance, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null.'); - final List args = (message as List?)!; - final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null, expected non-null int.'); - final URL? arg_url = (args[1] as URL?); - assert(arg_url != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null, expected non-null URL.'); - final bool? arg_isStale = (args[2] as bool?); - assert(arg_isStale != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.URLResolvingBookmarkDataResponse.pigeon_newInstance was null, expected non-null bool.'); - try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call(arg_url!, arg_isStale!) ?? - URLResolvingBookmarkDataResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - url: arg_url!, - isStale: arg_isStale!, - ), - arg_pigeon_instanceIdentifier!, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - @override - URLResolvingBookmarkDataResponse pigeon_copy() { - return URLResolvingBookmarkDataResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - url: url, - isStale: isStale, - ); - } -} - -class URL extends PigeonInternalProxyApiBaseClass { - /// Constructs [URL] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - URL.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); - - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecURL = - _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - URL Function()? pigeon_newInstance, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance was null.'); - final List args = (message as List?)!; - final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.URL.pigeon_newInstance was null, expected non-null int.'); - try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - URL.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - static Future fileURLWithPath( - String path, { - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) async { - if (PigeonOverrides.uRL_fileURLWithPath != null) { - return PigeonOverrides.uRL_fileURLWithPath!(path); - } - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.URL.fileURLWithPath'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([path]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as URL?); - } - } - - static Future resolvingBookmarkData( - Uint8List data, - List options, - URL? relativeTo, { - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) async { - if (PigeonOverrides.uRL_resolvingBookmarkData != null) { - return PigeonOverrides.uRL_resolvingBookmarkData!( - data, - options, - relativeTo, - ); - } - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.URL.resolvingBookmarkData'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([data, options, relativeTo]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as URLResolvingBookmarkDataResponse?)!; - } - } - - Future path() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecURL; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.URL.path'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as String?)!; - } - } - - Future bookmarkData( - List options, - List? keys, - URL? relativeTo, - ) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecURL; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.URL.bookmarkData'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, options, keys, relativeTo]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as Uint8List?)!; - } - } - - Future startAccessingSecurityScopedResource() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecURL; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.URL.startAccessingSecurityScopedResource'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future stopAccessingSecurityScopedResource() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecURL; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.URL.stopAccessingSecurityScopedResource'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - @override - URL pigeon_copy() { - return URL.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ); - } -} - -class FileHandle extends PigeonInternalProxyApiBaseClass { - factory FileHandle.forReadingFromUrl({ - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - required URL url, - }) { - if (PigeonOverrides.fileHandle_forReadingFromUrl != null) { - return PigeonOverrides.fileHandle_forReadingFromUrl!(url: url); - } - return FileHandle.pigeon_forReadingFromUrl( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - url: url, - ); - } - - @protected - FileHandle.pigeon_forReadingFromUrl({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - required URL url, - }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileHandle.forReadingFromUrl'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier, url]); - () async { - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - }(); - } - - /// Constructs [FileHandle] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - FileHandle.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); - - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileHandle = - _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - FileHandle Function()? pigeon_newInstance, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance was null.'); - final List args = (message as List?)!; - final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.FileHandle.pigeon_newInstance was null, expected non-null int.'); - try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - Future readUpToCount(int count) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileHandle.readUpToCount'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, count]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as Uint8List?); - } - } - - Future readToEnd() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileHandle.readToEnd'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as Uint8List?); - } - } - - Future close() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileHandle.close'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - @override - FileHandle pigeon_copy() { - return FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ); - } -} - -class FileManager extends PigeonInternalProxyApiBaseClass { - /// Constructs [FileManager] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - FileManager.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); - - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileManager = - _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - - static final FileManager _defaultManager = pigeonVar_defaultManager(); - - static FileManager get defaultManager => - PigeonOverrides.fileManager_defaultManager ?? _defaultManager; - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - FileManager Function()? pigeon_newInstance, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final BasicMessageChannel< - Object?> pigeonVar_channel = BasicMessageChannel< - Object?>( - 'dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null.'); - final List args = (message as List?)!; - final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_ios.FileManager.pigeon_newInstance was null, expected non-null int.'); - try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileManager.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - static FileManager pigeonVar_defaultManager() { - final FileManager pigeonVar_instance = FileManager.pigeon_detached(); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); - final BinaryMessenger pigeonVar_binaryMessenger = - ServicesBinding.instance.defaultBinaryMessenger; - final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance - .addDartCreatedInstance(pigeonVar_instance); - () async { - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.defaultManager'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - }(); - return pigeonVar_instance; - } - - Future fileExists(String atPath) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.fileExists'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future isReadableFile(String atPath) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.isReadableFile'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - Future fileModificationDate(String atPath) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.fileModificationDate'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as int?); - } - } - - Future fileSize(String atPath) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileManager; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const String pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_ios.FileManager.fileSize'; - final BasicMessageChannel pigeonVar_channel = - BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, atPath]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as int?); - } - } - - @override - FileManager pigeon_copy() { - return FileManager.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ); - } -} - diff --git a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart b/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart deleted file mode 100644 index e09207c59693..000000000000 --- a/packages/cross_file/cross_file_ios/lib/src/ios_cross_file.dart +++ /dev/null @@ -1,142 +0,0 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:cross_file_ios/src/foundation.g.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; - -// Note for me: Will probs need a `static Future method(Uint8List bookmarkData` method -// instead to create persistent file. -base class IOSXFile extends PlatformScopedStorageXFile { - IOSXFile(super.params) : super.implementation(); - - late final Future _originalUrl = URL.fileURLWithPath(params.uri); - - late final Future _bookmarkUrl = () async { - final URL? url = await _originalUrl; - if (url case URL url) { - final bool canRead = await url.startAccessingSecurityScopedResource(); - if (canRead) { - try { - final Uint8List? bookmarkData = await url.bookmarkData([], [], null); - if (bookmarkData case Uint8List bookmarkData) { - final URLResolvingBookmarkDataResponse response = await URL - .resolvingBookmarkData(bookmarkData, [], null); - if (response.isStale) { - return null; - } - return response.url; - } - } finally { - await url.stopAccessingSecurityScopedResource(); - } - } - } - - return null; - }(); - - @override - Future canRead() async { - final URL? bookmarkUrl = await _bookmarkUrl; - if (bookmarkUrl case URL bookmarkUrl) { - return FileManager.defaultManager.isReadableFile( - await bookmarkUrl.path(), - ); - } - - return false; - } - - @override - Future exists() async { - final URL? bookmarkUrl = await _bookmarkUrl; - if (bookmarkUrl case URL bookmarkUrl) { - return FileManager.defaultManager.fileExists(await bookmarkUrl.path()); - } - - return false; - } - - @override - Future lastModified() async { - final URL? bookmarkUrl = await _bookmarkUrl; - if (bookmarkUrl case URL bookmarkUrl) { - final int? lastModifiedSinceEpoch = await FileManager.defaultManager - .fileModificationDate(await bookmarkUrl.path()); - if (lastModifiedSinceEpoch case int lastModifiedSinceEpoch) { - return DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch); - } - } - - throw UnsupportedError('cant read: ${params.uri}'); - } - - @override - Future length() async { - final URL? bookmarkUrl = await _bookmarkUrl; - if (bookmarkUrl case URL bookmarkUrl) { - final int? fileSize = await FileManager.defaultManager.fileSize( - await bookmarkUrl.path(), - ); - if (fileSize case int fileSize) { - return fileSize; - } - } - - throw UnsupportedError('cant read: ${params.uri}'); - } - - @override - Future delete() { - // TODO: implement delete - throw UnimplementedError(); - } - - @override - Stream openRead([int? start, int? end]) async* { - if (await _bookmarkUrl case URL url) { - final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); - try { - Uint8List? bytes = await fileHandle.readUpToCount(4 * 1024); - while (bytes != null && bytes.isNotEmpty) { - yield bytes; - // TODO: this is only supported on ios 13.4 - bytes = await fileHandle.readUpToCount(4 * 1024); - } - } finally { - await fileHandle.close(); - } - } else { - throw UnsupportedError('Cant access bytes to file: ${params.uri}'); - } - } - - @override - Future readAsBytes() async { - if (await _bookmarkUrl case URL url) { - final FileHandle fileHandle = FileHandle.forReadingFromUrl(url: url); - try { - final Uint8List? bytes = await fileHandle.readToEnd(); - - if (bytes case Uint8List bytes) { - return bytes; - } - } finally { - await fileHandle.close(); - } - } - - throw UnsupportedError('Cant access bytes to file: ${params.uri}'); - } - - @override - Future readAsString({Encoding encoding = utf8}) async { - return encoding.decode(await readAsBytes()); - } - - @override - Future name() { - // TODO: implement name - throw UnimplementedError(); - } -} diff --git a/packages/cross_file/cross_file_ios/pigeons/copyright.txt b/packages/cross_file/cross_file_ios/pigeons/copyright.txt deleted file mode 100644 index 07e5f8598a80..000000000000 --- a/packages/cross_file/cross_file_ios/pigeons/copyright.txt +++ /dev/null @@ -1,3 +0,0 @@ -Copyright 2013 The Flutter Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. diff --git a/packages/cross_file/cross_file_ios/pigeons/foundation.dart b/packages/cross_file/cross_file_ios/pigeons/foundation.dart deleted file mode 100644 index 04bdd79963ac..000000000000 --- a/packages/cross_file/cross_file_ios/pigeons/foundation.dart +++ /dev/null @@ -1,70 +0,0 @@ -import 'package:pigeon/pigeon.dart'; - -@ConfigurePigeon( - PigeonOptions( - dartOut: 'lib/src/foundation.g.dart', - swiftOut: 'ios/Classes/proxies/Foundation.g.swift', - copyrightHeader: 'pigeons/copyright.txt', - ), -) -enum URLBookmarkCreationOptions { minimalBookmark, suitableForBookmarkOptions } - -enum URLResourceKeyEnum { isDirectoryKey, parentDirectoryURLKey } - -enum URLBookmarkResolutionOptions { withoutUI, withoutMounting } - -@ProxyApi() -abstract class URLResolvingBookmarkDataResponse { - late final URL url; - late final bool isStale; -} - -@ProxyApi() -abstract class URL { - @static - URL? fileURLWithPath(String path); - - @static - URLResolvingBookmarkDataResponse resolvingBookmarkData( - Uint8List data, - List options, - URL? relativeTo, - ); - - String path(); - - Uint8List bookmarkData( - List options, - List? keys, - URL? relativeTo, - ); - - bool startAccessingSecurityScopedResource(); - - void stopAccessingSecurityScopedResource(); -} - -@ProxyApi() -abstract class FileHandle { - FileHandle.forReadingFromUrl(URL url); - - Uint8List? readUpToCount(int count); - - Uint8List? readToEnd(); - - void close(); -} - -@ProxyApi() -abstract class FileManager { - @static - late final FileManager defaultManager; - - bool fileExists(String atPath); - - bool isReadableFile(String atPath); - - int? fileModificationDate(String atPath); - - int? fileSize(String atPath); -} diff --git a/packages/cross_file/cross_file_ios/pubspec.yaml b/packages/cross_file/cross_file_ios/pubspec.yaml deleted file mode 100644 index e2d5511771b1..000000000000 --- a/packages/cross_file/cross_file_ios/pubspec.yaml +++ /dev/null @@ -1,31 +0,0 @@ -name: cross_file_ios -description: "A new Flutter plugin project." -version: 0.0.1 -publish_to: none - -environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" - -flutter: - plugin: - implements: cross_file - platforms: - ios: - pluginClass: CrossFileIOSPlugin - dartPluginClass: CrossFileIOS - -dependencies: - flutter: - sdk: flutter - cross_file_platform_interface: - path: ../cross_file_platform_interface - -dev_dependencies: - flutter_test: - sdk: flutter - pigeon: - git: - url: git@github.com:bparrishMines/packages.git - ref: pigeon_helper - path: packages/pigeon diff --git a/packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart b/packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart deleted file mode 100644 index 1a1a1df6a14d..000000000000 --- a/packages/cross_file/cross_file_ios/test/cross_file_ios_method_channel_test.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_ios/cross_file_ios_method_channel.dart'; - -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - MethodChannelCrossFileIos platform = MethodChannelCrossFileIos(); - const MethodChannel channel = MethodChannel('cross_file_ios'); - - setUp(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( - channel, - (MethodCall methodCall) async { - return '42'; - }, - ); - }); - - tearDown(() { - TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null); - }); - - test('getPlatformVersion', () async { - expect(await platform.getPlatformVersion(), '42'); - }); -} diff --git a/packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart b/packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart deleted file mode 100644 index cff9c160310d..000000000000 --- a/packages/cross_file/cross_file_ios/test/cross_file_ios_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:cross_file_ios/cross_file_ios.dart'; -import 'package:cross_file_ios/cross_file_ios_platform_interface.dart'; -import 'package:cross_file_ios/cross_file_ios_method_channel.dart'; -import 'package:plugin_platform_interface/plugin_platform_interface.dart'; - -class MockCrossFileIosPlatform - with MockPlatformInterfaceMixin - implements CrossFileIosPlatform { - - @override - Future getPlatformVersion() => Future.value('42'); -} - -void main() { - final CrossFileIosPlatform initialPlatform = CrossFileIosPlatform.instance; - - test('$MethodChannelCrossFileIos is the default instance', () { - expect(initialPlatform, isInstanceOf()); - }); - - test('getPlatformVersion', () async { - CrossFileIos crossFileIosPlugin = CrossFileIos(); - MockCrossFileIosPlatform fakePlatform = MockCrossFileIosPlatform(); - CrossFileIosPlatform.instance = fakePlatform; - - expect(await crossFileIosPlugin.getPlatformVersion(), '42'); - }); -} From 5a773b119df4806507e89467ec902d67c3163616 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:24:43 -0500 Subject: [PATCH 128/398] compiling code --- .../cross_file/cross_file/example/lib/main.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index 24ef4b992d9e..928f0c3077f1 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:file_selector/file_selector.dart'; -import 'package:cross_file/cross_file.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -19,13 +18,14 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); - final String? fileName = await file.name() ?? file.uri; - - if (!context.mounted) { + if (file == null) { + // User canceled the dialog. return; } - if (file case final XFile file) { + final String fileName = await file.name() ?? file.uri; + + if (context.mounted) { switch (mime.lookupMimeType(fileName)) { case final String mimeType when mimeType.startsWith('text'): await showDialog( @@ -35,7 +35,7 @@ class FileOpenScreen extends StatelessWidget { case final String mimeType when mimeType.startsWith('image'): case final String mimeType when mimeType.startsWith('application'): case null: - debugPrint('Unsupported file type: ${file.path}'); + debugPrint('Unsupported file type: $fileName'); return; } } @@ -78,7 +78,7 @@ class TextDisplay extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(file.path), + title: Text(file.uri), content: Scrollbar( child: SingleChildScrollView( child: FutureBuilder( From abb58f2cf4d9d8b0ac02974d4310bb2d0720bf61 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:26:31 -0500 Subject: [PATCH 129/398] undo file_selector changes --- .../FileSelectorApiImpl.java | 36 ---- .../GeneratedFileSelectorApi.java | 149 ++++++++-------- .../example/lib/open_text_page.dart | 11 +- .../example/pubspec.yaml | 2 - .../lib/src/file_selector_android.dart | 18 -- .../lib/src/file_selector_api.g.dart | 160 +++++++++--------- .../pigeons/file_selector_api.dart | 3 - .../file_selector_android/pubspec.yaml | 2 - .../ios/Runner.xcodeproj/project.pbxproj | 19 --- .../xcshareddata/xcschemes/Runner.xcscheme | 2 - .../example/lib/open_text_page.dart | 17 +- .../file_selector_ios/example/pubspec.yaml | 2 - .../FileSelectorPlugin.swift | 21 --- .../file_selector_ios/messages.g.swift | 40 ++--- .../lib/file_selector_ios.dart | 16 -- .../file_selector_ios/lib/src/messages.g.dart | 88 ++++------ .../file_selector_ios/pigeons/messages.dart | 3 - .../file_selector_ios/pubspec.yaml | 2 - 18 files changed, 210 insertions(+), 381 deletions(-) diff --git a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java index aa1941b6e0a8..2504c9e00b8d 100644 --- a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java +++ b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/FileSelectorApiImpl.java @@ -131,42 +131,6 @@ public void onResult(int resultCode, @Nullable Intent data) { } } - @Override - public void openFile2(@Nullable String initialDirectory, @NonNull GeneratedFileSelectorApi.FileTypes allowedTypes, @NonNull GeneratedFileSelectorApi.NullableResult result) { - final Intent intent = objectFactory.newIntent(Intent.ACTION_OPEN_DOCUMENT); - intent.addCategory(Intent.CATEGORY_OPENABLE); - - setMimeTypes(intent, allowedTypes); - trySetInitialDirectory(intent, initialDirectory); - - try { - startActivityForResult( - intent, - OPEN_FILE, - new OnResultListener() { - @Override - public void onResult(int resultCode, @Nullable Intent data) { - if (resultCode == Activity.RESULT_OK && data != null) { - final Uri uri = data.getData(); - if (uri == null) { - // No data retrieved from opening file. - result.error(new Exception("Failed to retrieve data from opening file.")); - return; - } - - result.success(uri.toString()); - Log.d(TAG, "File path: " + uri); - } else { - result.success(null); - } - } - }); - } catch (Exception exception) { - result.error(exception); - } - } - - @Override public void openFiles( @Nullable String initialDirectory, diff --git a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java index 60c1094a6cdd..9f85509fb45a 100644 --- a/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java +++ b/packages/file_selector/file_selector_android/android/src/main/java/dev/flutter/packages/file_selector_android/GeneratedFileSelectorApi.java @@ -22,10 +22,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Objects; /** Generated class from Pigeon. */ @@ -41,8 +38,7 @@ public static class FlutterError extends RuntimeException { /** The error details. Must be a datatype supported by the api codec. */ public final Object details; - public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) - { + public FlutterError(@NonNull String code, @Nullable String message, @Nullable Object details) { super(message); this.code = code; this.details = details; @@ -61,7 +57,7 @@ protected static ArrayList wrapError(@NonNull Throwable exception) { errorList.add(exception.toString()); errorList.add(exception.getClass().getSimpleName()); errorList.add( - "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); } return errorList; } @@ -116,10 +112,15 @@ public void setMessage(@NonNull String setterArg) { @Override public boolean equals(Object o) { - if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { return false; } + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } FileSelectorNativeException that = (FileSelectorNativeException) o; - return fileSelectorExceptionCode.equals(that.fileSelectorExceptionCode) && message.equals(that.message); + return fileSelectorExceptionCode.equals(that.fileSelectorExceptionCode) + && message.equals(that.message); } @Override @@ -132,7 +133,8 @@ public static final class Builder { private @Nullable FileSelectorExceptionCode fileSelectorExceptionCode; @CanIgnoreReturnValue - public @NonNull Builder setFileSelectorExceptionCode(@NonNull FileSelectorExceptionCode setterArg) { + public @NonNull Builder setFileSelectorExceptionCode( + @NonNull FileSelectorExceptionCode setterArg) { this.fileSelectorExceptionCode = setterArg; return this; } @@ -161,10 +163,12 @@ ArrayList toList() { return toListResult; } - static @NonNull FileSelectorNativeException fromList(@NonNull ArrayList pigeonVar_list) { + static @NonNull FileSelectorNativeException fromList( + @NonNull ArrayList pigeonVar_list) { FileSelectorNativeException pigeonResult = new FileSelectorNativeException(); Object fileSelectorExceptionCode = pigeonVar_list.get(0); - pigeonResult.setFileSelectorExceptionCode((FileSelectorExceptionCode) fileSelectorExceptionCode); + pigeonResult.setFileSelectorExceptionCode( + (FileSelectorExceptionCode) fileSelectorExceptionCode); Object message = pigeonVar_list.get(1); pigeonResult.setMessage((String) message); return pigeonResult; @@ -247,10 +251,19 @@ public void setFileSelectorNativeException(@Nullable FileSelectorNativeException @Override public boolean equals(Object o) { - if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { return false; } + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } FileResponse that = (FileResponse) o; - return path.equals(that.path) && Objects.equals(mimeType, that.mimeType) && Objects.equals(name, that.name) && size.equals(that.size) && Arrays.equals(bytes, that.bytes) && Objects.equals(fileSelectorNativeException, that.fileSelectorNativeException); + return path.equals(that.path) + && Objects.equals(mimeType, that.mimeType) + && Objects.equals(name, that.name) + && size.equals(that.size) + && Arrays.equals(bytes, that.bytes) + && Objects.equals(fileSelectorNativeException, that.fileSelectorNativeException); } @Override @@ -305,7 +318,8 @@ public static final class Builder { private @Nullable FileSelectorNativeException fileSelectorNativeException; @CanIgnoreReturnValue - public @NonNull Builder setFileSelectorNativeException(@Nullable FileSelectorNativeException setterArg) { + public @NonNull Builder setFileSelectorNativeException( + @Nullable FileSelectorNativeException setterArg) { this.fileSelectorNativeException = setterArg; return this; } @@ -347,7 +361,8 @@ ArrayList toList() { Object bytes = pigeonVar_list.get(4); pigeonResult.setBytes((byte[]) bytes); Object fileSelectorNativeException = pigeonVar_list.get(5); - pigeonResult.setFileSelectorNativeException((FileSelectorNativeException) fileSelectorNativeException); + pigeonResult.setFileSelectorNativeException( + (FileSelectorNativeException) fileSelectorNativeException); return pigeonResult; } } @@ -385,8 +400,12 @@ public void setExtensions(@NonNull List setterArg) { @Override public boolean equals(Object o) { - if (this == o) { return true; } - if (o == null || getClass() != o.getClass()) { return false; } + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } FileTypes that = (FileTypes) o; return mimeTypes.equals(that.mimeTypes) && extensions.equals(that.extensions); } @@ -448,10 +467,13 @@ private PigeonCodec() {} @Override protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) { switch (type) { - case (byte) 129: { - Object value = readValue(buffer); - return value == null ? null : FileSelectorExceptionCode.values()[((Long) value).intValue()]; - } + case (byte) 129: + { + Object value = readValue(buffer); + return value == null + ? null + : FileSelectorExceptionCode.values()[((Long) value).intValue()]; + } case (byte) 130: return FileSelectorNativeException.fromList((ArrayList) readValue(buffer)); case (byte) 131: @@ -483,7 +505,6 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) { } } - /** Asynchronous error handling return type for non-nullable API method returns. */ public interface Result { /** Success case callback method for handling returns. */ @@ -511,43 +532,57 @@ public interface VoidResult { /** * An API to call to native code to select files or directories. * - * Generated interface from Pigeon that represents a handler of messages from Flutter. + *

Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface FileSelectorApi { /** * Opens a file dialog for loading files and returns a file path. * - * Returns `null` if user cancels the operation. + *

Returns `null` if user cancels the operation. */ - void openFile(@Nullable String initialDirectory, @NonNull FileTypes allowedTypes, @NonNull NullableResult result); - - void openFile2(@Nullable String initialDirectory, @NonNull FileTypes allowedTypes, @NonNull NullableResult result); + void openFile( + @Nullable String initialDirectory, + @NonNull FileTypes allowedTypes, + @NonNull NullableResult result); /** - * Opens a file dialog for loading files and returns a list of file responses - * chosen by the user. + * Opens a file dialog for loading files and returns a list of file responses chosen by the + * user. */ - void openFiles(@Nullable String initialDirectory, @NonNull FileTypes allowedTypes, @NonNull Result> result); + void openFiles( + @Nullable String initialDirectory, + @NonNull FileTypes allowedTypes, + @NonNull Result> result); /** * Opens a file dialog for loading directories and returns a directory path. * - * Returns `null` if user cancels the operation. + *

Returns `null` if user cancels the operation. */ - void getDirectoryPath(@Nullable String initialDirectory, @NonNull NullableResult result); + void getDirectoryPath( + @Nullable String initialDirectory, @NonNull NullableResult result); /** The codec used by FileSelectorApi. */ static @NonNull MessageCodec getCodec() { return PigeonCodec.INSTANCE; } - /**Sets up an instance of `FileSelectorApi` to handle messages through the `binaryMessenger`. */ + /** + * Sets up an instance of `FileSelectorApi` to handle messages through the `binaryMessenger`. + */ static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable FileSelectorApi api) { setUp(binaryMessenger, "", api); } - static void setUp(@NonNull BinaryMessenger binaryMessenger, @NonNull String messageChannelSuffix, @Nullable FileSelectorApi api) { + + static void setUp( + @NonNull BinaryMessenger binaryMessenger, + @NonNull String messageChannelSuffix, + @Nullable FileSelectorApi api) { messageChannelSuffix = messageChannelSuffix.isEmpty() ? "" : "." + messageChannelSuffix; { BasicMessageChannel channel = new BasicMessageChannel<>( - binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile" + messageChannelSuffix, getCodec()); + binaryMessenger, + "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile" + + messageChannelSuffix, + getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { @@ -577,37 +612,10 @@ public void error(Throwable error) { { BasicMessageChannel channel = new BasicMessageChannel<>( - binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile2" + messageChannelSuffix, getCodec()); - if (api != null) { - channel.setMessageHandler( - (message, reply) -> { - ArrayList wrapped = new ArrayList<>(); - ArrayList args = (ArrayList) message; - String initialDirectoryArg = (String) args.get(0); - FileTypes allowedTypesArg = (FileTypes) args.get(1); - NullableResult resultCallback = - new NullableResult() { - public void success(String result) { - wrapped.add(0, result); - reply.reply(wrapped); - } - - public void error(Throwable error) { - ArrayList wrappedError = wrapError(error); - reply.reply(wrappedError); - } - }; - - api.openFile2(initialDirectoryArg, allowedTypesArg, resultCallback); - }); - } else { - channel.setMessageHandler(null); - } - } - { - BasicMessageChannel channel = - new BasicMessageChannel<>( - binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles" + messageChannelSuffix, getCodec()); + binaryMessenger, + "dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles" + + messageChannelSuffix, + getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { @@ -637,7 +645,10 @@ public void error(Throwable error) { { BasicMessageChannel channel = new BasicMessageChannel<>( - binaryMessenger, "dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath" + messageChannelSuffix, getCodec()); + binaryMessenger, + "dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath" + + messageChannelSuffix, + getCodec()); if (api != null) { channel.setMessageHandler( (message, reply) -> { diff --git a/packages/file_selector/file_selector_android/example/lib/open_text_page.dart b/packages/file_selector/file_selector_android/example/lib/open_text_page.dart index a2180c6cf1dc..5469e580146b 100644 --- a/packages/file_selector/file_selector_android/example/lib/open_text_page.dart +++ b/packages/file_selector/file_selector_android/example/lib/open_text_page.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_android/cross_file_android.dart'; -import 'package:file_selector_android/file_selector_android.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:flutter/material.dart'; @@ -19,20 +17,15 @@ class OpenTextPage extends StatelessWidget { extensions: ['txt', 'json'], uniformTypeIdentifiers: ['public.text'], ); - final AndroidXFile? file = await FileSelectorAndroid().openFile2( + final XFile? file = await FileSelectorPlatform.instance.openFile( acceptedTypeGroups: [typeGroup], ); if (file == null) { // Operation was canceled by the user. return; } - final String fileName = 'Some Name'; + final String fileName = file.name; final String fileContent = await file.readAsString(); - print(await file.exists()); - print(await file.canRead()); - print(await file.length()); - print(await file.lastModified()); - print(await file.readAsBytes()); if (context.mounted) { await showDialog( diff --git a/packages/file_selector/file_selector_android/example/pubspec.yaml b/packages/file_selector/file_selector_android/example/pubspec.yaml index 0f2483493f9c..52f274b2edf1 100644 --- a/packages/file_selector/file_selector_android/example/pubspec.yaml +++ b/packages/file_selector/file_selector_android/example/pubspec.yaml @@ -7,8 +7,6 @@ environment: flutter: ">=3.32.0" dependencies: - cross_file_android: - path: ../../../cross_file/cross_file_android file_selector_android: # When depending on this package from a real application you should use: # file_selector_android: ^x.y.z diff --git a/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart b/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart index 5b55a1ef3603..461ede2e67e4 100644 --- a/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart +++ b/packages/file_selector/file_selector_android/lib/src/file_selector_android.dart @@ -4,7 +4,6 @@ // ignore_for_file: public_member_api_docs -import 'package:cross_file_android/cross_file_android.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:flutter/cupertino.dart'; @@ -36,23 +35,6 @@ class FileSelectorAndroid extends FileSelectorPlatform { return file == null ? null : _xFileFromFileResponse(file); } - Future openFile2({ - List? acceptedTypeGroups, - String? initialDirectory, - String? confirmButtonText, - }) async { - final String? path = await _api.openFile2( - initialDirectory, - _fileTypesFromTypeGroups(acceptedTypeGroups), - ); - - if (path case final String path) { - return AndroidXFile(PlatformXFileCreationParams(path: path)); - } - - return null; - } - @override Future> openFiles({ List? acceptedTypeGroups, diff --git a/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart b/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart index deaa438542c0..07663232cdea 100644 --- a/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart +++ b/packages/file_selector/file_selector_android/lib/src/file_selector_api.g.dart @@ -17,21 +17,25 @@ PlatformException _createConnectionError(String channelName) { message: 'Unable to establish connection on channel: "$channelName".', ); } + bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed - .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + a.indexed.every( + ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), + ); } if (a is Map && b is Map) { - return a.length == b.length && a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + return a.length == b.length && + a.entries.every( + (MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key]), + ); } return a == b; } - enum FileSelectorExceptionCode { securityException, ioException, @@ -50,14 +54,12 @@ class FileSelectorNativeException { String message; List _toList() { - return [ - fileSelectorExceptionCode, - message, - ]; + return [fileSelectorExceptionCode, message]; } Object encode() { - return _toList(); } + return _toList(); + } static FileSelectorNativeException decode(Object result) { result as List; @@ -70,7 +72,8 @@ class FileSelectorNativeException { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes bool operator ==(Object other) { - if (other is! FileSelectorNativeException || other.runtimeType != runtimeType) { + if (other is! FileSelectorNativeException || + other.runtimeType != runtimeType) { return false; } if (identical(this, other)) { @@ -81,8 +84,7 @@ class FileSelectorNativeException { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()) -; + int get hashCode => Object.hashAll(_toList()); } class FileResponse { @@ -119,7 +121,8 @@ class FileResponse { } Object encode() { - return _toList(); } + return _toList(); + } static FileResponse decode(Object result) { result as List; @@ -147,29 +150,23 @@ class FileResponse { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()) -; + int get hashCode => Object.hashAll(_toList()); } class FileTypes { - FileTypes({ - required this.mimeTypes, - required this.extensions, - }); + FileTypes({required this.mimeTypes, required this.extensions}); List mimeTypes; List extensions; List _toList() { - return [ - mimeTypes, - extensions, - ]; + return [mimeTypes, extensions]; } Object encode() { - return _toList(); } + return _toList(); + } static FileTypes decode(Object result) { result as List; @@ -193,11 +190,9 @@ class FileTypes { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()) -; + int get hashCode => Object.hashAll(_toList()); } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -205,16 +200,16 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileSelectorExceptionCode) { + } else if (value is FileSelectorExceptionCode) { buffer.putUint8(129); writeValue(buffer, value.index); - } else if (value is FileSelectorNativeException) { + } else if (value is FileSelectorNativeException) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is FileResponse) { + } else if (value is FileResponse) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else if (value is FileTypes) { + } else if (value is FileTypes) { buffer.putUint8(132); writeValue(buffer, value.encode()); } else { @@ -225,14 +220,14 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: final int? value = readValue(buffer) as int?; return value == null ? null : FileSelectorExceptionCode.values[value]; - case 130: + case 130: return FileSelectorNativeException.decode(readValue(buffer)!); - case 131: + case 131: return FileResponse.decode(readValue(buffer)!); - case 132: + case 132: return FileTypes.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -245,9 +240,13 @@ class FileSelectorApi { /// Constructor for [FileSelectorApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - FileSelectorApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + FileSelectorApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -257,14 +256,21 @@ class FileSelectorApi { /// Opens a file dialog for loading files and returns a file path. /// /// Returns `null` if user cancels the operation. - Future openFile(String? initialDirectory, FileTypes allowedTypes) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + Future openFile( + String? initialDirectory, + FileTypes allowedTypes, + ) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [initialDirectory, allowedTypes], ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory, allowedTypes]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -280,39 +286,23 @@ class FileSelectorApi { } } - Future openFile2(String? initialDirectory, FileTypes allowedTypes) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFile2$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory, allowedTypes]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as String?); - } - } - /// Opens a file dialog for loading files and returns a list of file responses /// chosen by the user. - Future> openFiles(String? initialDirectory, FileTypes allowedTypes) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + Future> openFiles( + String? initialDirectory, + FileTypes allowedTypes, + ) async { + final String pigeonVar_channelName = + 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.openFiles$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [initialDirectory, allowedTypes], ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory, allowedTypes]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -337,13 +327,17 @@ class FileSelectorApi { /// /// Returns `null` if user cancels the operation. Future getDirectoryPath(String? initialDirectory) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + final String pigeonVar_channelName = + 'dev.flutter.pigeon.file_selector_android.FileSelectorApi.getDirectoryPath$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [initialDirectory], ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([initialDirectory]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { diff --git a/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart b/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart index dba4dd278f64..1aa94ae1bc9a 100644 --- a/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart +++ b/packages/file_selector/file_selector_android/pigeons/file_selector_api.dart @@ -51,9 +51,6 @@ abstract class FileSelectorApi { @async FileResponse? openFile(String? initialDirectory, FileTypes allowedTypes); - @async - String? openFile2(String? initialDirectory, FileTypes allowedTypes); - /// Opens a file dialog for loading files and returns a list of file responses /// chosen by the user. @async diff --git a/packages/file_selector/file_selector_android/pubspec.yaml b/packages/file_selector/file_selector_android/pubspec.yaml index 9275d2508e9c..042236bfae85 100644 --- a/packages/file_selector/file_selector_android/pubspec.yaml +++ b/packages/file_selector/file_selector_android/pubspec.yaml @@ -18,8 +18,6 @@ flutter: pluginClass: FileSelectorAndroidPlugin dependencies: - cross_file_android: - path: ../../cross_file/cross_file_android file_selector_platform_interface: ^2.5.0 flutter: sdk: flutter diff --git a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj index 67839eeb7bf4..3a0c60083fa5 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -180,7 +180,6 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - C04A430C6B9C2A1A0197124B /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -352,23 +351,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - C04A430C6B9C2A1A0197124B /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -604,7 +586,6 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = PT2QK76LGP; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 88f2c790671c..7607cff6ce75 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -44,7 +44,6 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit" shouldUseLaunchSchemeArgsEnv = "YES"> ['txt', 'json'], - //uniformTypeIdentifiers: ['somefile.txt'], + uniformTypeIdentifiers: ['public.text'], ); - final IOSXFile? file = await FileSelectorIOS().openFile2( - //acceptedTypeGroups: [typeGroup], + final XFile? file = await FileSelectorPlatform.instance.openFile( + acceptedTypeGroups: [typeGroup], ); if (file == null) { // Operation was canceled by the user. return; } - //final String fileName = file.name; - print(file.params.path); - print(await file.canRead()); - print(await file.exists()); - print(await file.lastModified()); - print(await file.length()); + final String fileName = file.name; final String fileContent = await file.readAsString(); if (context.mounted) { await showDialog( context: context, - builder: (BuildContext context) => TextDisplay('FileName', fileContent), + builder: (BuildContext context) => TextDisplay(fileName, fileContent), ); } } diff --git a/packages/file_selector/file_selector_ios/example/pubspec.yaml b/packages/file_selector/file_selector_ios/example/pubspec.yaml index 06961ea06ea4..928cbc3def68 100644 --- a/packages/file_selector/file_selector_ios/example/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/example/pubspec.yaml @@ -8,8 +8,6 @@ environment: flutter: ">=3.38.0" dependencies: - cross_file_ios: - path: ../../../cross_file/cross_file_ios # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.2 diff --git a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift index c280163408bd..5b9f5d7c229e 100644 --- a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift +++ b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/FileSelectorPlugin.swift @@ -78,26 +78,5 @@ public class FileSelectorPlugin: NSObject, FlutterPlugin, FileSelectorApi { ) } } - - func openFile2(config: FileSelectorConfig, completion: @escaping (Result<[String], any Error>) -> Void) { - let completionBridge = PickerCompletionBridge(completion: completion, owner: self) - let documentPicker = - documentPickerViewControllerOverride - ?? UIDocumentPickerViewController( - documentTypes: config.utis, - in: .open) - documentPicker.allowsMultipleSelection = config.allowMultiSelection - documentPicker.delegate = completionBridge - let presenter = - self.viewPresenterOverride ?? UIApplication.shared.delegate?.window??.rootViewController - if let presenter = presenter { - pendingCompletions.insert(completionBridge) - presenter.present(documentPicker, animated: true, completion: nil) - } else { - completion( - .failure(PigeonError(code: "error", message: "Missing root view controller.", details: nil)) - ) - } - } } diff --git a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift index 5c4d2b7d6a09..bcb5609f5024 100644 --- a/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift +++ b/packages/file_selector/file_selector_ios/ios/file_selector_ios/Sources/file_selector_ios/messages.g.swift @@ -110,12 +110,12 @@ func deepEqualsmessages(_ lhs: Any?, _ rhs: Any?) -> Bool { func deepHashmessages(value: Any?, hasher: inout Hasher) { if let valueList = value as? [AnyHashable] { - for item in valueList { deepHashmessages(value: item, hasher: &hasher) } - return + for item in valueList { deepHashmessages(value: item, hasher: &hasher) } + return } if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { + for key in valueDict.keys { hasher.combine(key) deepHashmessages(value: valueDict[key]!, hasher: &hasher) } @@ -129,14 +129,11 @@ func deepHashmessages(value: Any?, hasher: inout Hasher) { return hasher.combine(String(describing: value)) } - - /// Generated class from Pigeon that represents data sent in messages. struct FileSelectorConfig: Hashable { var utis: [String] var allowMultiSelection: Bool - // swift-format-ignore: AlwaysUseLowerCamelCase static func fromList(_ pigeonVar_list: [Any?]) -> FileSelectorConfig? { let utis = pigeonVar_list[0] as! [String] @@ -154,7 +151,8 @@ struct FileSelectorConfig: Hashable { ] } static func == (lhs: FileSelectorConfig, rhs: FileSelectorConfig) -> Bool { - return deepEqualsmessages(lhs.toList(), rhs.toList()) } + return deepEqualsmessages(lhs.toList(), rhs.toList()) + } func hash(into hasher: inout Hasher) { deepHashmessages(value: toList(), hasher: &hasher) } @@ -196,20 +194,23 @@ class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter()) } - /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol FileSelectorApi { func openFile(config: FileSelectorConfig, completion: @escaping (Result<[String], Error>) -> Void) - func openFile2(config: FileSelectorConfig, completion: @escaping (Result<[String], Error>) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class FileSelectorApiSetup { static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared } /// Sets up an instance of `FileSelectorApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: FileSelectorApi?, messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: FileSelectorApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - let openFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let openFileChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { openFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -226,22 +227,5 @@ class FileSelectorApiSetup { } else { openFileChannel.setMessageHandler(nil) } - let openFile2Channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile2\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - openFile2Channel.setMessageHandler { message, reply in - let args = message as! [Any?] - let configArg = args[0] as! FileSelectorConfig - api.openFile2(config: configArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - openFile2Channel.setMessageHandler(nil) - } } } diff --git a/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart b/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart index 3bae4a709cb4..2f6f241333f0 100644 --- a/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart +++ b/packages/file_selector/file_selector_ios/lib/file_selector_ios.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_ios/cross_file_ios.dart'; import 'package:file_selector_platform_interface/file_selector_platform_interface.dart'; import 'package:flutter/foundation.dart' show visibleForTesting; @@ -35,21 +34,6 @@ class FileSelectorIOS extends FileSelectorPlatform { return path.isEmpty ? null : XFile(path.first); } - Future openFile2({ - List? acceptedTypeGroups, - String? initialDirectory, - String? confirmButtonText, - }) async { - final List paths = await _hostApi.openFile2( - FileSelectorConfig( - utis: _allowedUtiListFromTypeGroups(acceptedTypeGroups), - ), - ); - return paths.isEmpty - ? null - : IOSXFile(PlatformSharedStorageXFileCreationParams(path: paths.first)); - } - @override Future> openFiles({ List? acceptedTypeGroups, diff --git a/packages/file_selector/file_selector_ios/lib/src/messages.g.dart b/packages/file_selector/file_selector_ios/lib/src/messages.g.dart index 6c231c0b766c..6e3795225ca9 100644 --- a/packages/file_selector/file_selector_ios/lib/src/messages.g.dart +++ b/packages/file_selector/file_selector_ios/lib/src/messages.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v25.5.0), do not edit directly. +// Autogenerated from Pigeon (v26.1.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -17,21 +17,25 @@ PlatformException _createConnectionError(String channelName) { message: 'Unable to establish connection on channel: "$channelName".', ); } + bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed - .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); + a.indexed.every( + ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), + ); } if (a is Map && b is Map) { - return a.length == b.length && a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); + return a.length == b.length && + a.entries.every( + (MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key]), + ); } return a == b; } - class FileSelectorConfig { FileSelectorConfig({ this.utis = const [], @@ -43,14 +47,12 @@ class FileSelectorConfig { bool allowMultiSelection; List _toList() { - return [ - utis, - allowMultiSelection, - ]; + return [utis, allowMultiSelection]; } Object encode() { - return _toList(); } + return _toList(); + } static FileSelectorConfig decode(Object result) { result as List; @@ -74,11 +76,9 @@ class FileSelectorConfig { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()) -; + int get hashCode => Object.hashAll(_toList()); } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -86,7 +86,7 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileSelectorConfig) { + } else if (value is FileSelectorConfig) { buffer.putUint8(129); writeValue(buffer, value.encode()); } else { @@ -97,7 +97,7 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: return FileSelectorConfig.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -109,9 +109,13 @@ class FileSelectorApi { /// Constructor for [FileSelectorApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - FileSelectorApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + FileSelectorApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -119,41 +123,17 @@ class FileSelectorApi { final String pigeonVar_messageChannelSuffix; Future> openFile(FileSelectorConfig config) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([config]); - final List? pigeonVar_replyList = - await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as List?)!.cast(); - } - } - - Future> openFile2(FileSelectorConfig config) async { - final String pigeonVar_channelName = 'dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile2$pigeonVar_messageChannelSuffix'; - final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, + final String pigeonVar_channelName = + 'dev.flutter.pigeon.file_selector_ios.FileSelectorApi.openFile$pigeonVar_messageChannelSuffix'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [config], ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([config]); final List? pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { diff --git a/packages/file_selector/file_selector_ios/pigeons/messages.dart b/packages/file_selector/file_selector_ios/pigeons/messages.dart index 6e6259a41ca0..857e888c2846 100644 --- a/packages/file_selector/file_selector_ios/pigeons/messages.dart +++ b/packages/file_selector/file_selector_ios/pigeons/messages.dart @@ -26,7 +26,4 @@ abstract class FileSelectorApi { @async @ObjCSelector('openFileSelectorWithConfig:') List openFile(FileSelectorConfig config); - - @async - List openFile2(FileSelectorConfig config); } diff --git a/packages/file_selector/file_selector_ios/pubspec.yaml b/packages/file_selector/file_selector_ios/pubspec.yaml index 693ba52dc06a..c57f2cd1b9ff 100644 --- a/packages/file_selector/file_selector_ios/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/pubspec.yaml @@ -17,8 +17,6 @@ flutter: pluginClass: FileSelectorPlugin dependencies: - cross_file_ios: - path: ../../cross_file/cross_file_ios file_selector_platform_interface: ^2.3.0 flutter: sdk: flutter From 1fe476d87558d18ef12c7b36e691dc75f67a8861 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 6 Feb 2026 15:37:43 -0500 Subject: [PATCH 130/398] fix failing unit tests --- packages/cross_file/cross_file_android/example/pubspec.yaml | 5 ++++- packages/cross_file/cross_file_darwin/example/pubspec.yaml | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 5031c8112dbc..5eda5008a4b7 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -13,7 +13,10 @@ dependencies: # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - path: ../ + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_android file_selector: git: url: https://github.com/bparrishMines/packages diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 8f938bd02383..a329c38dd9d9 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -13,7 +13,10 @@ dependencies: # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - path: ../ + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_darwin cupertino_icons: ^1.0.8 file_selector: git: From 3179eaef03b8eac077baff93996c842ce8d6d19e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:15:14 -0500 Subject: [PATCH 131/398] some lints --- .../cross_file/cross_file/example/lib/readme_excerpts.dart | 6 +++--- .../cross_file_android/pigeons/android_library.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 319bc465ef53..1ec003a48995 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -10,9 +10,9 @@ Future instantiateXFile() async { // #docregion Instantiate final file = XFile('assets/hello.txt'); - print('File information:'); - print('- URI: ${file.uri}'); - print('- Name: ${await file.name()}'); + debugPrint('File information:'); + debugPrint('- URI: ${file.uri}'); + debugPrint('- Name: ${await file.name()}'); if (await file.canRead()) { final String fileContent = await file.readAsString(); diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index 7da2829f0349..ebc0bdf319dd 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -111,7 +111,7 @@ abstract class InputStreamReadBytesResponse { kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), ) abstract class InputStream { - // TODO: maybe return empty list instead of new class? + // TODO(bparrishMines): maybe return empty list instead of new class? /// Reads some number of bytes from the input stream and stores them into the /// returns them. InputStreamReadBytesResponse readBytes(int len); From d447ee97c24eb196f71c48b221d9f7813263c331 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:44:05 -0500 Subject: [PATCH 132/398] update android fix maybe --- .../InputStreamReadBytesResponse.kt | 26 - .../cross_file_android/ProxyApiRegistrar.kt | 4 - .../proxies/AndroidLibrary.g.kt | 684 ++++++++---------- .../proxies/InputStreamProxyApi.kt | 9 +- .../InputStreamReadBytesResponseProxyApi.kt | 26 - .../cross_file_android/example/lib/main.dart | 11 +- .../cross_file_android/example/pubspec.yaml | 5 + .../lib/src/android_library.g.dart | 448 +++++------- .../android_scoped_storage_cross_file.dart | 12 +- .../pigeons/android_library.dart | 21 +- ...ndroid_scoped_storage_cross_file_test.dart | 5 +- ..._scoped_storage_cross_file_test.mocks.dart | 25 +- 12 files changed, 505 insertions(+), 771 deletions(-) delete mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt delete mode 100644 packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt deleted file mode 100644 index d77fd0471131..000000000000 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/InputStreamReadBytesResponse.kt +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android - -/** Represents the result of reading bytes from an [java.io.InputStream]. */ -data class InputStreamReadBytesResponse(val returnValue: Int, val bytes: ByteArray) { - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as InputStreamReadBytesResponse - - if (returnValue != other.returnValue) return false - if (!bytes.contentEquals(other.bytes)) return false - - return true - } - - override fun hashCode(): Int { - var result = returnValue - result = 31 * result + bytes.contentHashCode() - return result - } -} diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt index 86d01a26826d..0644c3313a52 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -31,10 +31,6 @@ open class ProxyApiRegistrar(binaryMessenger: BinaryMessenger, var context: Cont return ContentResolverProxyApi(this) } - override fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse { - return InputStreamReadBytesResponseProxyApi(this) - } - override fun getPigeonApiInputStream(): PigeonApiInputStream { return InputStreamProxyApi(this) } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index 3836008adb39..eccc68ae07f3 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.5), do not edit directly. +// Autogenerated from Pigeon (v26.1.7), do not edit directly. // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") @@ -10,17 +10,16 @@ package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer - private object AndroidLibraryPigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError( - "channel-error", "Unable to establish connection on channel: '$channelName'.", "") - } + return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } fun wrapResult(result: Any?): List { return listOf(result) @@ -28,48 +27,50 @@ private object AndroidLibraryPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf(exception.code, exception.message, exception.details) + listOf( + exception.code, + exception.message, + exception.details + ) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) + ) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. - * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError ( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() /** * Maintains instances used to communicate with the corresponding objects in Dart. * - * Objects stored in this container are represented by an object in Dart that is also stored in an - * InstanceManager with the same identifier. + * Objects stored in this container are represented by an object in Dart that is also stored in + * an InstanceManager with the same identifier. * * When an instance is added with an identifier, either can be used to retrieve the other. * - * Added instances are added as a weak reference and a strong reference. When the strong reference - * is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the - * strong reference is removed and then the identifier is retrieved with the intention to pass the - * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the - * instance is recreated. The strong reference will then need to be removed manually again. + * Added instances are added as a weak reference and a strong reference. When the strong + * reference is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong + * reference is removed and then the identifier is retrieved with the intention to pass the identifier + * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance + * is recreated. The strong reference will then need to be removed manually again. */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class AndroidLibraryPigeonInstanceManager( - private val finalizationListener: PigeonFinalizationListener -) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ +class AndroidLibraryPigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface PigeonFinalizationListener { fun onFinalize(identifier: Long) } @@ -138,20 +139,19 @@ class AndroidLibraryPigeonInstanceManager( private const val tag = "PigeonInstanceManager" /** - * Instantiate a new manager with a listener for garbage collected weak references. + * Instantiate a new manager with a listener for garbage collected weak + * references. * * When the manager is no longer needed, [stopFinalizationListener] must be called. */ - fun create( - finalizationListener: PigeonFinalizationListener - ): AndroidLibraryPigeonInstanceManager { + fun create(finalizationListener: PigeonFinalizationListener): AndroidLibraryPigeonInstanceManager { return AndroidLibraryPigeonInstanceManager(finalizationListener) } } /** - * Removes `identifier` and return its associated strongly referenced instance, if present, from - * the manager. + * Removes `identifier` and return its associated strongly referenced instance, if present, + * from the manager. */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() @@ -161,13 +161,15 @@ class AndroidLibraryPigeonInstanceManager( /** * Retrieves the identifier paired with an instance, if present, otherwise `null`. * + * * If the manager contains a strong reference to `instance`, it will return the identifier * associated with `instance`. If the manager contains only a weak reference to `instance`, a new * strong reference to `instance` will be added and will need to be removed again with [remove]. * + * * If this method returns a nonnull identifier, this method also expects the Dart - * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart - * instance the identifier is associated with. + * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. */ fun getIdentifierForStrongReference(instance: Any?): Long? { logWarningIfFinalizationListenerHasStopped() @@ -184,9 +186,9 @@ class AndroidLibraryPigeonInstanceManager( /** * Adds a new instance that was instantiated from Dart. * - * The same instance can be added multiple times, but each identifier must be unique. This allows - * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are - * equal) to both be added. + * The same instance can be added multiple times, but each identifier must be unique. This + * allows two objects that are equivalent (e.g. the `equals` method returns true and their + * hashcodes are equal) to both be added. * * [identifier] must be >= 0 and unique. */ @@ -198,15 +200,13 @@ class AndroidLibraryPigeonInstanceManager( /** * Adds a new unique instance that was instantiated from the host platform. * - * If the manager contains [instance], this returns the corresponding identifier. If the manager - * does not contain [instance], this adds the instance and returns a unique identifier for that - * [instance]. + * If the manager contains [instance], this returns the corresponding identifier. If the + * manager does not contain [instance], this adds the instance and returns a unique + * identifier for that [instance]. */ fun addHostCreatedInstance(instance: Any): Long { logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { - "Instance of ${instance.javaClass} has already been added." - } + require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } val identifier = nextIdentifier++ addInstance(instance, identifier) return identifier @@ -290,43 +290,39 @@ class AndroidLibraryPigeonInstanceManager( private fun logWarningIfFinalizationListenerHasStopped() { if (hasFinalizationListenerStopped()) { Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped.") + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped." + ) } } } + /** Generated API for managing the Dart and native `InstanceManager`s. */ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { companion object { /** The codec used by AndroidLibraryPigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { AndroidLibraryPigeonCodec() } + val codec: MessageCodec by lazy { + AndroidLibraryPigeonCodec() + } /** * Sets up an instance of `AndroidLibraryPigeonInstanceManagerApi` to handle messages from the * `binaryMessenger`. */ - fun setUpMessageHandlers( - binaryMessenger: BinaryMessenger, - instanceManager: AndroidLibraryPigeonInstanceManager? - ) { + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: AndroidLibraryPigeonInstanceManager?) { run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) if (instanceManager != null) { channel.setMessageHandler { message, reply -> val args = message as List val identifierArg = args[0] as Long - val wrapped: List = - try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -334,20 +330,15 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) if (instanceManager != null) { channel.setMessageHandler { _, reply -> - val wrapped: List = - try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -357,9 +348,9 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { - val channelName = - "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) +{ + val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(identifierArg)) { if (it is List<*>) { @@ -370,13 +361,13 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } /** - * Provides implementations for each ProxyApi implementation and provides access to resources needed - * by any implementation. + * Provides implementations for each ProxyApi implementation and provides access to resources + * needed by any implementation. */ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { /** Whether APIs should ignore calling to Dart. */ @@ -393,23 +384,24 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary init { val api = AndroidLibraryPigeonInstanceManagerApi(binaryMessenger) - instanceManager = - AndroidLibraryPigeonInstanceManager.create( - object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier") - } - } - } - }) + instanceManager = AndroidLibraryPigeonInstanceManager.create( + object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier" + ) + } + } + } + } + ) } /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` - * to the Dart `InstanceManager`. + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of + * `DocumentFile` to the Dart `InstanceManager`. */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile @@ -426,8 +418,8 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to - * the Dart `InstanceManager`. + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of + * `InputStream` to the Dart `InstanceManager`. */ abstract fun getPigeonApiInputStream(): PigeonApiInputStream @@ -437,7 +429,6 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } - fun tearDown() { AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) @@ -445,17 +436,17 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } - -private class AndroidLibraryPigeonProxyApiBaseCodec( - val registrar: AndroidLibraryPigeonProxyApiRegistrar -) : AndroidLibraryPigeonCodec() { +private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibraryPigeonProxyApiRegistrar) : AndroidLibraryPigeonCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 128.toByte() -> { val identifier: Long = readValue(buffer) as Long val instance: Any? = registrar.instanceManager.getInstance(identifier) if (instance == null) { - Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") + Log.e( + "PigeonProxyApiBaseCodec", + "Failed to find instance with identifier: $identifier" + ) } return instance } @@ -464,27 +455,16 @@ private class AndroidLibraryPigeonProxyApiBaseCodec( } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || - value is ByteArray || - value is Double || - value is DoubleArray || - value is FloatArray || - value is Int || - value is IntArray || - value is List<*> || - value is Long || - value is LongArray || - value is Map<*, *> || - value is String || - value == null) { + if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { super.writeValue(stream, value) return } fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception") + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception" + ) } if (value is androidx.documentfile.provider.DocumentFile) { @@ -493,19 +473,22 @@ private class AndroidLibraryPigeonProxyApiBaseCodec( logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) } } - } else if (value is android.content.ContentResolver) { + } + else if (value is android.content.ContentResolver) { registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { + } + else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) } } - } else if (value is java.io.InputStream) { + } + else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) @@ -518,36 +501,34 @@ private class AndroidLibraryPigeonProxyApiBaseCodec( stream.write(128) writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) } - else -> - throw IllegalArgumentException( - "Unsupported value: '$value' of type '${value.javaClass.name}'") + else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") } } } - private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } /** - * Representation of a document backed by either a android.provider.DocumentsProvider or a raw file - * on disk. + * Representation of a document backed by either a + * android.provider.DocumentsProvider or a raw file on disk. * * See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { +abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { /** Create a DocumentFile representing the single document at the given Uri. */ abstract fun fromSingleUri(singleUri: String): androidx.documentfile.provider.DocumentFile + /** + * Create a DocumentFile representing the document tree rooted at the given + * Uri. + */ abstract fun fromTreeUri(treeUri: String): androidx.documentfile.provider.DocumentFile /** Indicates whether the current context is allowed to read from this file. */ @@ -560,8 +541,8 @@ abstract class PigeonApiDocumentFile( abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean /** - * Returns the time when this file was last modified, measured in milliseconds since January 1st, - * 1970, midnight. + * Returns the time when this file was last modified, measured in + * milliseconds since January 1st, 1970, midnight. */ abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long @@ -574,10 +555,11 @@ abstract class PigeonApiDocumentFile( /** Indicates if this file represents a *directory*. */ abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - /** Returns an list of files contained in the directory represented by this file. */ - abstract fun listFiles( - pigeon_instance: androidx.documentfile.provider.DocumentFile - ): List + /** + * Returns an list of files contained in the directory represented by this + * file. + */ + abstract fun listFiles(pigeon_instance: androidx.documentfile.provider.DocumentFile): List /** A Uri for the underlying document represented by this file. */ abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String @@ -590,24 +572,18 @@ abstract class PigeonApiDocumentFile( fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val singleUriArg = args[1] as String - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.fromSingleUri(singleUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(singleUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -615,24 +591,18 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val treeUriArg = args[1] as String - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.fromTreeUri(treeUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromTreeUri(treeUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -640,21 +610,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -662,19 +627,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -682,19 +644,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -702,21 +661,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -724,19 +678,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -744,19 +695,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.isFile(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.isFile(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -764,21 +712,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.isDirectory(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.isDirectory(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -786,21 +729,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.listFiles(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.listFiles(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -808,19 +746,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.getUri(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.getUri(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -828,21 +763,16 @@ abstract class PigeonApiDocumentFile( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.DocumentFile.getName", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getName", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = - try { - listOf(api.getName(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.getName(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -854,19 +784,16 @@ abstract class PigeonApiDocumentFile( @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, - callback: (Result) -> Unit - ) { + fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" @@ -874,17 +801,17 @@ abstract class PigeonApiDocumentFile( channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } /** * This class provides applications access to the content model. @@ -892,40 +819,32 @@ abstract class PigeonApiDocumentFile( * See https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { - /** Helper field for accessing the `ContentResolver` from the current Android `Context`. */ +abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * Helper field for accessing the `ContentResolver` from the current Android + * `Context`. + */ abstract fun instance(): android.content.ContentResolver /** Open a stream on to the content associated with a content URI. */ - abstract fun openInputStream( - pigeon_instance: android.content.ContentResolver, - uri: String - ): java.io.InputStream? + abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val wrapped: List = - try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -933,22 +852,17 @@ abstract class PigeonApiContentResolver( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as android.content.ContentResolver val uriArg = args[1] as String - val wrapped: List = - try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -960,19 +874,16 @@ abstract class PigeonApiContentResolver( @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: android.content.ContentResolver, - callback: (Result) -> Unit - ) { + fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" @@ -980,85 +891,78 @@ abstract class PigeonApiContentResolver( channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } /** Return type for [InputStream.readBytes] that handles returning two values. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { - abstract fun returnValue( - pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - ): Long +abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * The total number of bytes read into `bytes`, or -1 if there is no more + * data because the end of the stream has been reached. + * + * The returned value when calling the native `InputStream.readBytes` method. + */ + abstract fun bytesRead(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long - abstract fun bytes( - pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse - ): ByteArray + /** The byte array into which the data is read. */ + abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray @Suppress("LocalVariableName", "FunctionName") - /** - * Creates a Dart instance of InputStreamReadBytesResponse and attaches it to - * [pigeon_instanceArg]. - */ - fun pigeon_newInstance( - pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, - callback: (Result) -> Unit - ) { + /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) - val returnValueArg = returnValue(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val bytesReadArg = bytesRead(pigeon_instanceArg) val bytesArg = bytes(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec - val channelName = - "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" + val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(pigeon_identifierArg, returnValueArg, bytesArg)) { + channel.send(listOf(pigeon_identifierArg, bytesReadArg, bytesArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } /** - * This abstract class is the superclass of all classes representing an input stream of bytes. + * This abstract class is the superclass of all classes representing an input + * stream of bytes. * * See https://developer.android.com/reference/java/io/InputStream. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStream( - open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar -) { - /** Reads some number of bytes from the input stream and stores them into the returns them. */ - abstract fun readBytes( - pigeon_instance: java.io.InputStream, - len: Long - ): dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse +abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { + /** + * Reads some number of bytes from the input stream and stores them into the + * returns them. + */ + abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): ByteArray /** Reads all remaining bytes from the input stream. */ abstract fun readAllBytes(pigeon_instance: java.io.InputStream): ByteArray @@ -1071,22 +975,17 @@ abstract class PigeonApiInputStream( fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val lenArg = args[1] as Long - val wrapped: List = - try { - listOf(api.readBytes(pigeon_instanceArg, lenArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.readBytes(pigeon_instanceArg, lenArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1094,21 +993,16 @@ abstract class PigeonApiInputStream( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, - "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", - codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = - try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1116,20 +1010,17 @@ abstract class PigeonApiInputStream( } } run { - val channel = - BasicMessageChannel( - binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val nArg = args[1] as Long - val wrapped: List = - try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -1141,19 +1032,16 @@ abstract class PigeonApiInputStream( @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance( - pigeon_instanceArg: java.io.InputStream, - callback: (Result) -> Unit - ) { + fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) +{ if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = - pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" @@ -1161,15 +1049,15 @@ abstract class PigeonApiInputStream( channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback( - Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } + } diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt index a0a90efab0be..58003c31e3d8 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -19,9 +19,14 @@ class InputStreamProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : override fun readBytes( pigeon_instance: InputStream, len: Long, - ): InputStreamReadBytesResponse { + ): ByteArray { val bytes = ByteArray(len.toInt()) - return InputStreamReadBytesResponse(pigeon_instance.read(bytes), bytes) + val bytesRead = pigeon_instance.read(bytes) + if (bytesRead == -1) { + return byteArrayOf() + } else { + return bytes.copyOfRange(0, bytesRead) + } } override fun readAllBytes(pigeon_instance: InputStream): ByteArray { diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt deleted file mode 100644 index 925c6f4365e6..000000000000 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseProxyApi.kt +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -import dev.flutter.packages.cross_file_android.ProxyApiRegistrar - -/** - * ProxyApi implementation for [InputStreamReadBytesResponse]. - * - * This class may handle instantiating native object instances that are attached to a Dart instance - * or handle method calls on the associated native class or an instance of that class. - */ -class InputStreamReadBytesResponseProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : - PigeonApiInputStreamReadBytesResponse(pigeonRegistrar) { - - override fun returnValue(pigeon_instance: InputStreamReadBytesResponse): Long { - return pigeon_instance.returnValue.toLong() - } - - override fun bytes(pigeon_instance: InputStreamReadBytesResponse): ByteArray { - return pigeon_instance.bytes - } -} diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 3a945a835a29..e8750ae6a9cf 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:flutter_driver/driver_extension.dart'; @@ -24,14 +25,16 @@ class FileOpenScreen extends StatelessWidget { const FileOpenScreen({super.key}); Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); + final PlatformXFile? file = (await openFile())?.platform; + + final String? filename = await file?.name(); if (!context.mounted) { return; } if (file case final XFile file) { - switch (mime.lookupMimeType(file.name)) { + switch (mime.lookupMimeType(filename ?? file.uri)) { case final String mimeType when mimeType.startsWith('text'): await showDialog( context: context, @@ -40,7 +43,7 @@ class FileOpenScreen extends StatelessWidget { case final String mimeType when mimeType.startsWith('image'): case final String mimeType when mimeType.startsWith('application'): case null: - debugPrint('Unsupported file type: ${file.path}'); + debugPrint('Unsupported file type: ${file.uri}'); return; } } @@ -83,7 +86,7 @@ class TextDisplay extends StatelessWidget { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(file.path), + title: Text(file.uri), content: Scrollbar( child: SingleChildScrollView( child: FutureBuilder( diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 5eda5008a4b7..63143c4eceb7 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -17,6 +17,11 @@ dependencies: url: https://github.com/bparrishMines/packages ref: new_crossfile path: packages/cross_file/cross_file_android + cross_file_platform_interface: + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface file_selector: git: url: https://github.com/bparrishMines/packages diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index ba08ace33382..dc24413557a5 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.5), do not edit directly. +// Autogenerated from Pigeon (v26.1.7), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -9,8 +9,7 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' - show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -21,11 +20,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -34,7 +29,6 @@ List wrapResponse({ } return [error.code, error.message, error.details]; } - /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -46,11 +40,11 @@ List wrapResponse({ class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String singleUri})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [DocumentFile.fromTreeUri]. static DocumentFile Function({required String treeUri})? - documentFile_fromTreeUri; + documentFile_fromTreeUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -75,7 +69,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -145,10 +139,9 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> - _weakInstances = >{}; - final Map _strongInstances = - {}; + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -161,8 +154,7 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = - _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -170,21 +162,11 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers( - instanceManager: instanceManager, - ); - DocumentFile.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - ContentResolver.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStream.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -201,9 +183,8 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference( - instance, - ); + _weakInstances[identifier] = + WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -264,21 +245,15 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference( - int identifier, - ) { - final PigeonInternalProxyApiBaseClass? weakInstance = - _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = - _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance - .pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = - WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -300,10 +275,7 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance( - PigeonInternalProxyApiBaseClass instance, - int identifier, - ) { + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -332,7 +304,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -345,35 +317,28 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert( - arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', - ); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); try { - (instanceManager ?? PigeonInstanceManager.instance).remove( - arg_identifier!, - ); + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -388,9 +353,8 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -433,31 +397,31 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference( - readValue(buffer)! as int, - ); - default: - return super.readValueOfType(type, buffer); - } - } + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } } + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -478,7 +442,6 @@ class _PigeonCodec extends StandardMessageCodec { } } } - /// Representation of a document backed by either a /// android.provider.DocumentsProvider or a raw file on disk. /// @@ -507,8 +470,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String singleUri, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -519,9 +482,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, singleUri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([pigeonVar_instanceIdentifier, singleUri]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -538,6 +500,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }(); } + /// Create a DocumentFile representing the document tree rooted at the given + /// Uri. factory DocumentFile.fromTreeUri({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, @@ -553,14 +517,16 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { ); } + /// Create a DocumentFile representing the document tree rooted at the given + /// Uri. @protected DocumentFile.pigeon_fromTreeUri({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, required String treeUri, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -571,9 +537,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, treeUri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel + .send([pigeonVar_instanceIdentifier, treeUri]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -611,46 +576,39 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -669,9 +627,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -703,9 +660,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -737,9 +693,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -772,9 +727,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -806,9 +760,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -840,9 +793,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -874,9 +826,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -909,9 +860,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -943,9 +893,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -977,9 +926,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1037,46 +985,39 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1100,9 +1041,8 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1131,9 +1071,8 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, uri], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, uri]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1167,75 +1106,71 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { InputStreamReadBytesResponse.pigeon_detached({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, - required this.returnValue, + required this.bytesRead, required this.bytes, }); - final int returnValue; + /// The total number of bytes read into `bytes`, or -1 if there is no more + /// data because the end of the stream has been reached. + /// + /// The returned value when calling the native `InputStream.readBytes` method. + final int bytesRead; + /// The byte array into which the data is read. final Uint8List bytes; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function(int returnValue, Uint8List bytes)? - pigeon_newInstance, + InputStreamReadBytesResponse Function( + int bytesRead, + Uint8List bytes, + )? pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', - ); - final int? arg_returnValue = (args[1] as int?); - assert( - arg_returnValue != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); + final int? arg_bytesRead = (args[1] as int?); + assert(arg_bytesRead != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert( - arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.', - ); + assert(arg_bytes != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call(arg_returnValue!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - returnValue: arg_returnValue!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call(arg_bytesRead!, arg_bytes!) ?? + InputStreamReadBytesResponse.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + bytesRead: arg_bytesRead!, + bytes: arg_bytes!, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1247,7 +1182,7 @@ class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { return InputStreamReadBytesResponse.pigeon_detached( pigeon_binaryMessenger: pigeon_binaryMessenger, pigeon_instanceManager: pigeon_instanceManager, - returnValue: returnValue, + bytesRead: bytesRead, bytes: bytes, ); } @@ -1279,46 +1214,39 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -1327,7 +1255,7 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// Reads some number of bytes from the input stream and stores them into the /// returns them. - Future readBytes(int len) async { + Future readBytes(int len) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -1338,9 +1266,8 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, len], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, len]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1356,7 +1283,7 @@ class InputStream extends PigeonInternalProxyApiBaseClass { message: 'Host platform returned null value for non-null return value.', ); } else { - return (pigeonVar_replyList[0] as InputStreamReadBytesResponse?)!; + return (pigeonVar_replyList[0] as Uint8List?)!; } } @@ -1372,9 +1299,8 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1406,9 +1332,8 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, n], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, n]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1436,3 +1361,4 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } + diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 98efdb4c48d1..6f32c7e24bcd 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -66,14 +66,12 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { await inputStream.skip(start); } - late android.InputStreamReadBytesResponse response; + late Uint8List bytes; do { - response = await inputStream.readBytes( - min(bytesToRead, maxByteArrayLen), - ); - yield response.bytes; - bytesToRead -= response.returnValue; - } while (response.returnValue > -1 && bytesToRead > 0); + bytes = await inputStream.readBytes(min(bytesToRead, maxByteArrayLen)); + yield bytes; + bytesToRead -= bytes.length; + } while (bytesToRead > 0 && bytes.isNotEmpty); } else { throw NullInputStreamError(params.uri); } diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index ebc0bdf319dd..2070a2250d6a 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -85,24 +85,6 @@ abstract class ContentResolver { InputStream? openInputStream(String uri); } -/// Return type for [InputStream.readBytes] that handles returning two values. -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions( - fullClassName: - 'dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse', - ), -) -abstract class InputStreamReadBytesResponse { - /// The total number of bytes read into `bytes`, or -1 if there is no more - /// data because the end of the stream has been reached. - /// - /// The returned value when calling the native `InputStream.readBytes` method. - late final int bytesRead; - - /// The byte array into which the data is read. - late final Uint8List bytes; -} - /// This abstract class is the superclass of all classes representing an input /// stream of bytes. /// @@ -111,10 +93,9 @@ abstract class InputStreamReadBytesResponse { kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), ) abstract class InputStream { - // TODO(bparrishMines): maybe return empty list instead of new class? /// Reads some number of bytes from the input stream and stores them into the /// returns them. - InputStreamReadBytesResponse readBytes(int len); + Uint8List readBytes(int len); /// Reads all remaining bytes from the input stream. Uint8List readAllBytes(); diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart index a7c85762c3be..8eb575acab8b 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart @@ -307,10 +307,7 @@ void setUpInputStreamWithBytes( final List bytesRead = remainingBytes.take(len).toList(); remainingBytes = remainingBytes.skip(len); - return android.InputStreamReadBytesResponse.pigeon_detached( - returnValue: remainingBytes.isEmpty ? -1 : bytesRead.length, - bytes: Uint8List.fromList(bytesRead), - ); + return Uint8List.fromList(bytesRead); }); } diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart index 6392c7ba2670..8694dd65dee7 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart @@ -42,16 +42,8 @@ class _FakeDocumentFile_2 extends _i1.SmartFake implements _i2.DocumentFile { : super(parent, parentInvocation); } -class _FakeInputStreamReadBytesResponse_3 extends _i1.SmartFake - implements _i2.InputStreamReadBytesResponse { - _FakeInputStreamReadBytesResponse_3( - Object parent, - Invocation parentInvocation, - ) : super(parent, parentInvocation); -} - -class _FakeInputStream_4 extends _i1.SmartFake implements _i2.InputStream { - _FakeInputStream_4(Object parent, Invocation parentInvocation) +class _FakeInputStream_3 extends _i1.SmartFake implements _i2.InputStream { + _FakeInputStream_3(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } @@ -229,17 +221,12 @@ class MockInputStream extends _i1.Mock implements _i2.InputStream { as _i2.PigeonInstanceManager); @override - _i3.Future<_i2.InputStreamReadBytesResponse> readBytes(int? len) => + _i3.Future<_i5.Uint8List> readBytes(int? len) => (super.noSuchMethod( Invocation.method(#readBytes, [len]), - returnValue: _i3.Future<_i2.InputStreamReadBytesResponse>.value( - _FakeInputStreamReadBytesResponse_3( - this, - Invocation.method(#readBytes, [len]), - ), - ), + returnValue: _i3.Future<_i5.Uint8List>.value(_i5.Uint8List(0)), ) - as _i3.Future<_i2.InputStreamReadBytesResponse>); + as _i3.Future<_i5.Uint8List>); @override _i3.Future<_i5.Uint8List> readAllBytes() => @@ -261,7 +248,7 @@ class MockInputStream extends _i1.Mock implements _i2.InputStream { _i2.InputStream pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeInputStream_4( + returnValue: _FakeInputStream_3( this, Invocation.method(#pigeon_copy, []), ), From 81597b3a965c6c409f273f446cd677cc48d5f6f6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:48:25 -0500 Subject: [PATCH 133/398] remove old imports --- .../flutter/packages/cross_file_android/ProxyApiRegistrar.kt | 2 -- .../packages/cross_file_android/proxies/InputStreamProxyApi.kt | 1 - 2 files changed, 3 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt index 0644c3313a52..930748628b8f 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt @@ -9,11 +9,9 @@ import dev.flutter.packages.cross_file_android.proxies.AndroidLibraryPigeonProxy import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi import dev.flutter.packages.cross_file_android.proxies.InputStreamProxyApi -import dev.flutter.packages.cross_file_android.proxies.InputStreamReadBytesResponseProxyApi import dev.flutter.packages.cross_file_android.proxies.PigeonApiContentResolver import dev.flutter.packages.cross_file_android.proxies.PigeonApiDocumentFile import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStream -import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStreamReadBytesResponse import io.flutter.plugin.common.BinaryMessenger /** diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt index 58003c31e3d8..21df3f93bef3 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt @@ -4,7 +4,6 @@ package dev.flutter.packages.cross_file_android.proxies -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse import dev.flutter.packages.cross_file_android.ProxyApiRegistrar import java.io.InputStream From 60edb0d270917bd50f574124cba7032e50ce1a5a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:49:45 -0500 Subject: [PATCH 134/398] remove unsued classes --- .../proxies/AndroidLibrary.g.kt | 60 ------------ .../lib/src/android_library.g.dart | 93 ------------------- 2 files changed, 153 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index eccc68ae07f3..0c540f90fafe 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -411,12 +411,6 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary */ abstract fun getPigeonApiContentResolver(): PigeonApiContentResolver - /** - * An implementation of [PigeonApiInputStreamReadBytesResponse] used to add a new Dart instance of - * `InputStreamReadBytesResponse` to the Dart `InstanceManager`. - */ - abstract fun getPigeonApiInputStreamReadBytesResponse(): PigeonApiInputStreamReadBytesResponse - /** * An implementation of [PigeonApiInputStream] used to add a new Dart instance of * `InputStream` to the Dart `InstanceManager`. @@ -480,13 +474,6 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } - else if (value is dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse) { - registrar.getPigeonApiInputStreamReadBytesResponse().pigeon_newInstance(value) { - if (it.isFailure) { - logNewInstanceFailure("InputStreamReadBytesResponse", value, it.exceptionOrNull()) - } - } } else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { @@ -902,53 +889,6 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary } } -} -/** Return type for [InputStream.readBytes] that handles returning two values. */ -@Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStreamReadBytesResponse(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * The total number of bytes read into `bytes`, or -1 if there is no more - * data because the end of the stream has been reached. - * - * The returned value when calling the native `InputStream.readBytes` method. - */ - abstract fun bytesRead(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): Long - - /** The byte array into which the data is read. */ - abstract fun bytes(pigeon_instance: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse): ByteArray - - @Suppress("LocalVariableName", "FunctionName") - /** Creates a Dart instance of InputStreamReadBytesResponse and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse, callback: (Result) -> Unit) -{ - if (pigeonRegistrar.ignoreCallsToDart) { - callback( - Result.failure( - FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { - callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) - val bytesReadArg = bytesRead(pigeon_instanceArg) - val bytesArg = bytes(pigeon_instanceArg) - val binaryMessenger = pigeonRegistrar.binaryMessenger - val codec = pigeonRegistrar.codec - val channelName = "dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance" - val channel = BasicMessageChannel(binaryMessenger, channelName, codec) - channel.send(listOf(pigeon_identifierArg, bytesReadArg, bytesArg)) { - if (it is List<*>) { - if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) - } else { - callback(Result.success(Unit)) - } - } else { - callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } - } - } - } - } /** * This abstract class is the superclass of all classes representing an input diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index dc24413557a5..5c8424596c9d 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -165,7 +165,6 @@ class PigeonInstanceManager { _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStreamReadBytesResponse.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -1096,98 +1095,6 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { } } -/// Return type for [InputStream.readBytes] that handles returning two values. -class InputStreamReadBytesResponse extends PigeonInternalProxyApiBaseClass { - /// Constructs [InputStreamReadBytesResponse] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - InputStreamReadBytesResponse.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - required this.bytesRead, - required this.bytes, - }); - - /// The total number of bytes read into `bytes`, or -1 if there is no more - /// data because the end of the stream has been reached. - /// - /// The returned value when calling the native `InputStream.readBytes` method. - final int bytesRead; - - /// The byte array into which the data is read. - final Uint8List bytes; - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - InputStreamReadBytesResponse Function( - int bytesRead, - Uint8List bytes, - )? pigeon_newInstance, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null.'); - final List args = (message as List?)!; - final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); - final int? arg_bytesRead = (args[1] as int?); - assert(arg_bytesRead != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null int.'); - final Uint8List? arg_bytes = (args[2] as Uint8List?); - assert(arg_bytes != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStreamReadBytesResponse.pigeon_newInstance was null, expected non-null Uint8List.'); - try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call(arg_bytesRead!, arg_bytes!) ?? - InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - bytesRead: arg_bytesRead!, - bytes: arg_bytes!, - ), - arg_pigeon_instanceIdentifier!, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - @override - InputStreamReadBytesResponse pigeon_copy() { - return InputStreamReadBytesResponse.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - bytesRead: bytesRead, - bytes: bytes, - ); - } -} - /// This abstract class is the superclass of all classes representing an input /// stream of bytes. /// From 4ebe1efe650b852e41556975ac633141305f4785 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 18:59:39 -0500 Subject: [PATCH 135/398] fix example app on android --- packages/cross_file/cross_file_android/example/lib/main.dart | 3 +-- packages/cross_file/cross_file_android/example/pubspec.yaml | 5 ----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index e8750ae6a9cf..b44b55a34a7d 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:flutter_driver/driver_extension.dart'; @@ -25,7 +24,7 @@ class FileOpenScreen extends StatelessWidget { const FileOpenScreen({super.key}); Future _openFile(BuildContext context) async { - final PlatformXFile? file = (await openFile())?.platform; + final XFile? file = await openFile(); final String? filename = await file?.name(); diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 63143c4eceb7..5eda5008a4b7 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -17,11 +17,6 @@ dependencies: url: https://github.com/bparrishMines/packages ref: new_crossfile path: packages/cross_file/cross_file_android - cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface file_selector: git: url: https://github.com/bparrishMines/packages From a211972a82514382ddb756cec92fa6779d0225e4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 19:13:48 -0500 Subject: [PATCH 136/398] update references to test files --- .../example/ios/Runner.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index cbad8c8e53ea..966c37e3b23e 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -60,10 +60,10 @@ 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = ""; }; - 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FileHandleTests.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift; sourceTree = ""; }; - 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestBinaryMessenger.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift; sourceTree = ""; }; - 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = ""; }; + 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; + 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FileHandleTests.swift; path = ../../darwin/Tests/FileHandleTests.swift; sourceTree = SOURCE_ROOT; }; + 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestBinaryMessenger.swift; path = ../../darwin/Tests/TestBinaryMessenger.swift; sourceTree = SOURCE_ROOT; }; + 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = ../../darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = SOURCE_ROOT; }; 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; From 63d018afaa42483174e0ae9ae1fa216ec678f26a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 19:33:32 -0500 Subject: [PATCH 137/398] update example app on darwin --- .../cross_file_darwin/example/lib/main.dart | 60 ++++++++++--------- .../cross_file_darwin/example/pubspec.yaml | 21 ++++--- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index c66ed1242f9c..f92204768bff 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -18,24 +18,30 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); - if (!context.mounted) { - return; - } - if (file case final XFile file) { - switch (mime.lookupMimeType(file.path)) { + final String filename = await file.name() ?? file.uri; + + switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): - await showDialog( - context: context, - builder: (BuildContext context) => TextDisplay(file), - ); - case final String mimeType when mimeType.startsWith('image'): - case final String mimeType when mimeType.startsWith('application'): - case null: - debugPrint('Unsupported file type: ${file.path}'); + final String fileContents = await file.readAsString(); + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(filename: filename, fileContents: fileContents), + ); + } + case _: + debugPrint('File Uri: ${file.uri}'); + debugPrint('Filename: $filename'); + debugPrint('Can Read File: ${await file.canRead()}'); + debugPrint('File Length: ${await file.length()}'); + debugPrint('File Last Modified: ${await file.lastModified()}'); return; } } + + debugPrint('No file selected.'); } @override @@ -67,28 +73,24 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay(this.file, {super.key}); + const TextDisplay({ + super.key, + required this.filename, + required this.fileContents, + }); + + /// The name of the file. + final String filename; - /// The file. - final XFile file; + /// The contents of the file. + final String fileContents; @override Widget build(BuildContext context) { return AlertDialog( - title: Text(file.path), + title: Text(filename), content: Scrollbar( - child: SingleChildScrollView( - child: FutureBuilder( - future: file.readAsString(), - builder: (_, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!); - } else { - return const CircularProgressIndicator(); - } - }, - ), - ), + child: SingleChildScrollView(child: Text(fileContents)), ), actions: [ TextButton( diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index a329c38dd9d9..dadf3a801297 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -7,21 +7,11 @@ environment: flutter: ">=3.35.0" dependencies: - cross_file_darwin: - # When depending on this package from a real application you should use: - # cross_file_darwin: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_darwin cupertino_icons: ^1.0.8 file_selector: git: url: https://github.com/bparrishMines/packages - ref: new_crossfile + ref: new_file_selector path: packages/file_selector/file_selector flutter: sdk: flutter @@ -38,3 +28,12 @@ flutter: uses-material-design: true assets: - assets/hello.txt + +dependency_overrides: + cross_file_darwin: + # When depending on this package from a real application you should use: + # cross_file_darwin: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ \ No newline at end of file From d226f9342077f96cb13764a28da0d59100fb7c9a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:06:06 -0500 Subject: [PATCH 138/398] update android example app --- .../cross_file_android/example/lib/main.dart | 62 +++++++++---------- .../cross_file_android/example/pubspec.yaml | 19 +++--- 2 files changed, 40 insertions(+), 41 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index b44b55a34a7d..e7425847ba8a 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -26,26 +26,30 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); - final String? filename = await file?.name(); - - if (!context.mounted) { - return; - } - if (file case final XFile file) { - switch (mime.lookupMimeType(filename ?? file.uri)) { + final String filename = await file.name() ?? file.uri; + + switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): - await showDialog( - context: context, - builder: (BuildContext context) => TextDisplay(file), - ); - case final String mimeType when mimeType.startsWith('image'): - case final String mimeType when mimeType.startsWith('application'): - case null: - debugPrint('Unsupported file type: ${file.uri}'); + final String fileContents = await file.readAsString(); + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(filename: filename, fileContents: fileContents), + ); + } + case _: + debugPrint('File Uri: ${file.uri}'); + debugPrint('Filename: $filename'); + debugPrint('Can Read File: ${await file.canRead()}'); + debugPrint('File Length: ${await file.length()}'); + debugPrint('File Last Modified: ${await file.lastModified()}'); return; } } + + debugPrint('No file selected.'); } @override @@ -77,28 +81,24 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay(this.file, {super.key}); + const TextDisplay({ + super.key, + required this.filename, + required this.fileContents, + }); + + /// The name of the file. + final String filename; - /// The file. - final XFile file; + /// The contents of the file. + final String fileContents; @override Widget build(BuildContext context) { return AlertDialog( - title: Text(file.uri), + title: Text(filename), content: Scrollbar( - child: SingleChildScrollView( - child: FutureBuilder( - future: file.readAsString(), - builder: (_, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!); - } else { - return const CircularProgressIndicator(); - } - }, - ), - ), + child: SingleChildScrollView(child: Text(fileContents)), ), actions: [ TextButton( diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 5eda5008a4b7..1c12ae4314ba 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -7,16 +7,6 @@ environment: flutter: ">=3.35.0" dependencies: - cross_file_android: - # When depending on this package from a real application you should use: - # cross_file_android: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_android file_selector: git: url: https://github.com/bparrishMines/packages @@ -37,3 +27,12 @@ dev_dependencies: flutter: uses-material-design: true + +dependency_overrides: + # When depending on this package from a real application you should use: + # cross_file_android: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + cross_file_android: + path: ../ From 4a8e24606d4f5ff926dab963357058e3da17a707 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:20:53 -0500 Subject: [PATCH 139/398] try fix tests --- .../InputStreamReadBytesResponseTest.kt | 36 ------------------- .../proxies/InputStreamTest.kt | 5 ++- 2 files changed, 2 insertions(+), 39 deletions(-) delete mode 100644 packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt deleted file mode 100644 index 5540ca22376d..000000000000 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamReadBytesResponseTest.kt +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package dev.flutter.packages.cross_file_android.proxies - -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse -import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar -import kotlin.test.Test -import kotlin.test.assertEquals -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever - -class InputStreamReadBytesResponseTest { - @Test - fun returnValue() { - val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() - - val instance = mock() - val value = 0 - whenever(instance.returnValue).thenReturn(value) - - assertEquals(value.toLong(), api.returnValue(instance)) - } - - @Test - fun bytes() { - val api = TestProxyApiRegistrar().getPigeonApiInputStreamReadBytesResponse() - - val instance = mock() - val value = byteArrayOf(0xA1.toByte()) - whenever(instance.bytes).thenReturn(value) - - assertEquals(value, api.bytes(instance)) - } -} diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index c2e0fbf959c2..04590847b0dc 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -4,7 +4,6 @@ package dev.flutter.packages.cross_file_android.proxies -import dev.flutter.packages.cross_file_android.InputStreamReadBytesResponse import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar import java.io.ByteArrayInputStream import java.io.InputStream @@ -27,8 +26,8 @@ class InputStreamTest { whenever(instance.read(bytesCaptor.capture())).thenReturn(value) assertEquals( - api.readBytes(instance, len.toLong()), - InputStreamReadBytesResponse(value, bytesCaptor.value)) + api.readBytes(instance, len.toLong()), + value.toLong()) assertEquals(bytesCaptor.value.size, len) } From 1aa3ec6a3bde70ab52a871cdd18f64bb7f00b5b0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 7 Feb 2026 20:31:38 -0500 Subject: [PATCH 140/398] fix inputstream test --- .../cross_file_android/proxies/InputStreamTest.kt | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt index 04590847b0dc..636130334e0d 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt @@ -21,13 +21,11 @@ class InputStreamTest { val instance = mock() val bytesCaptor = ArgumentCaptor.forClass(ByteArray::class.java) - val len = 2 - val value = 3 + val len = 3 + val value = 2 whenever(instance.read(bytesCaptor.capture())).thenReturn(value) - assertEquals( - api.readBytes(instance, len.toLong()), - value.toLong()) + assertEquals(api.readBytes(instance, len.toLong()).size, value) assertEquals(bytesCaptor.value.size, len) } From 92cc9b3fe15ed78ca2520692fa38f4e10438e757 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 9 Feb 2026 20:38:09 -0500 Subject: [PATCH 141/398] open directory example --- .../cross_file_android/example/lib/main.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index e7425847ba8a..09ed025084f3 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -52,6 +52,28 @@ class FileOpenScreen extends StatelessWidget { debugPrint('No file selected.'); } + Future _openDirectory() async { + final XDirectory? directory = await getDirectoryPath(); + + if (directory != null) { + debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory exists: ${await directory.exists()}'); + + debugPrint('List of Entities:'); + await for (final XFileEntity entity in directory.list()) { + switch (entity) { + case final XFile file: + final String filename = await file.name() ?? file.uri; + debugPrint('\tFile: $filename'); + case final XDirectory directory: + debugPrint('\tDirectory: ${directory.uri}'); + } + } + } else { + debugPrint('No directory selected.'); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -71,6 +93,14 @@ class FileOpenScreen extends StatelessWidget { child: const Text('Open File'), onPressed: () => _openFile(context), ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open Directory'), + onPressed: () => _openDirectory(), + ), ], ), ), From a0aeddb28ee8cc6b6f442654896ad121346c772b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 9 Feb 2026 20:43:30 -0500 Subject: [PATCH 142/398] also works on ios --- .../cross_file_darwin/example/lib/main.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index f92204768bff..8545251fed60 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -44,6 +44,28 @@ class FileOpenScreen extends StatelessWidget { debugPrint('No file selected.'); } + Future _openDirectory() async { + final XDirectory? directory = await getDirectoryPath(); + + if (directory != null) { + debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory exists: ${await directory.exists()}'); + + debugPrint('List of Entities:'); + await for (final XFileEntity entity in directory.list()) { + switch (entity) { + case final XFile file: + final String filename = await file.name() ?? file.uri; + debugPrint('\tFile: $filename'); + case final XDirectory directory: + debugPrint('\tDirectory: ${directory.uri}'); + } + } + } else { + debugPrint('No directory selected.'); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -63,6 +85,14 @@ class FileOpenScreen extends StatelessWidget { child: const Text('Open File'), onPressed: () => _openFile(context), ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open Directory'), + onPressed: () => _openDirectory(), + ), ], ), ), From 1e4705829c5b9150972d647ce61ae8a3e8f26b65 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 9 Feb 2026 20:55:24 -0500 Subject: [PATCH 143/398] update example app for main plugin --- .../cross_file/example/lib/main.dart | 93 ++++++++++++------- 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index 928f0c3077f1..f6df294c1cba 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -18,27 +18,52 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); - if (file == null) { - // User canceled the dialog. - return; - } - - final String fileName = await file.name() ?? file.uri; + if (file != null) { + final String filename = await file.name() ?? file.uri; - if (context.mounted) { - switch (mime.lookupMimeType(fileName)) { + switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): - await showDialog( - context: context, - builder: (BuildContext context) => TextDisplay(file), - ); - case final String mimeType when mimeType.startsWith('image'): - case final String mimeType when mimeType.startsWith('application'): - case null: - debugPrint('Unsupported file type: $fileName'); + final String fileContents = await file.readAsString(); + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(filename: filename, fileContents: fileContents), + ); + } + case _: + debugPrint('File Uri: ${file.uri}'); + debugPrint('Filename: $filename'); + debugPrint('Can Read File: ${await file.canRead()}'); + debugPrint('File Length: ${await file.length()}'); + debugPrint('File Last Modified: ${await file.lastModified()}'); return; } } + + debugPrint('No file selected.'); + } + + Future _openDirectory() async { + final XDirectory? directory = await getDirectoryPath(); + + if (directory != null) { + debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory exists: ${await directory.exists()}'); + + debugPrint('List of Entities:'); + await for (final XFileEntity entity in directory.list()) { + switch (entity) { + case final XFile file: + final String filename = await file.name() ?? file.uri; + debugPrint('\tFile: $filename'); + case final XDirectory directory: + debugPrint('\tDirectory: ${directory.uri}'); + } + } + } else { + debugPrint('No directory selected.'); + } } @override @@ -60,6 +85,14 @@ class FileOpenScreen extends StatelessWidget { child: const Text('Open File'), onPressed: () => _openFile(context), ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open Directory'), + onPressed: () => _openDirectory(), + ), ], ), ), @@ -70,28 +103,24 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay(this.file, {super.key}); + const TextDisplay({ + super.key, + required this.filename, + required this.fileContents, + }); - /// The file. - final XFile file; + /// The name of the file. + final String filename; + + /// The contents of the file. + final String fileContents; @override Widget build(BuildContext context) { return AlertDialog( - title: Text(file.uri), + title: Text(filename), content: Scrollbar( - child: SingleChildScrollView( - child: FutureBuilder( - future: file.readAsString(), - builder: (_, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!); - } else { - return const CircularProgressIndicator(); - } - }, - ), - ), + child: SingleChildScrollView(child: Text(fileContents)), ), actions: [ TextButton( From e571580fee96c0b26bd61fe2b6cfdd7512716e53 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 9 Feb 2026 21:11:41 -0500 Subject: [PATCH 144/398] update for macos --- .../Classes/CrossFileDarwinPlugin.swift | 2 +- .../darwin/Classes/ProxyAPIRegistrar.swift | 7 ++ .../CrossFileDarwinApiImpl.swift | 7 ++ .../FileHandleProxyAPIDelegate.swift | 11 ++- .../macos/Runner.xcodeproj/project.pbxproj | 98 ++++++++++++++++++- .../cross_file_darwin/example/pubspec.yaml | 1 - 6 files changed, 121 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift index 21a87fe122ed..ee34131694ec 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift @@ -38,7 +38,7 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { let messenger = registrar.messenger #endif - CrossFileDarwinApiSetup.setUp(binaryMessenger: registrar.messenger(), api: nil) + CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: nil) proxyApiRegistrar!.ignoreCallsToDart = true proxyApiRegistrar!.tearDown() proxyApiRegistrar = nil diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift index bf01f5e8e29f..09d515badab7 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift @@ -2,7 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#if os(iOS) import Flutter +#elseif os(macOS) +import FlutterMacOS +#else +#error("Unsupported platform.") +#endif + import Foundation /// Implementation of `CrossFileDarwinApisPigeonProxyApiRegistrar` that provides any additional resources needed by API implementations. diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift index 454df655ac2a..1372a8736a9b 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift @@ -2,7 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#if os(iOS) import Flutter +#elseif os(macOS) +import FlutterMacOS +#else +#error("Unsupported platform.") +#endif + import Foundation /// Implementation of `CrossFileDarwinApi`. diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift index 05b73be383ff..67c030a9223b 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift @@ -2,7 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#if os(iOS) import Flutter +#elseif os(macOS) +import FlutterMacOS +#else +#error("Unsupported platform.") +#endif + import Foundation /// ProxyApi implementation for `FileHandle`. @@ -18,7 +25,7 @@ class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { throws -> FlutterStandardTypedData? { var data: Data? - if #available(iOS 13.4, *) { + if #available(iOS 13.4, macOS 10.15.4, *) { data = try pigeonInstance.read(upToCount: Int(count)) } else { data = pigeonInstance.readData(ofLength: Int(count)) @@ -35,7 +42,7 @@ class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { -> FlutterStandardTypedData? { var bytes: Data? - if #available(iOS 13.4, *) { + if #available(iOS 13.4, macOS 10.15.4, *) { bytes = try pigeonInstance.readToEnd() } else { bytes = pigeonInstance.readDataToEndOfFile() diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index c7fc52d02cad..e519e5c8c25d 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,12 +21,14 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 1E3F930A949E6BF1A392A157 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */; }; 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 9365FDE22965FC1D9207E2E0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63A129979C19E770A95C46BB /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -60,11 +62,12 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross_file_darwin_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cross_file_darwin_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -76,8 +79,15 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 63A129979C19E770A95C46BB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 68E94AA7D5658C9B4705BC78 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 6E84AA1E5316F40ABCA87AF9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 7255794ECF94B4FB91F39D79 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 95E600C17773E34356453E89 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 1E3F930A949E6BF1A392A157 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +103,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9365FDE22965FC1D9207E2E0 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,6 +137,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 91814838E1B0599FEE23D945 /* Pods */, ); sourceTree = ""; }; @@ -172,9 +185,25 @@ path = Runner; sourceTree = ""; }; + 91814838E1B0599FEE23D945 /* Pods */ = { + isa = PBXGroup; + children = ( + 95E600C17773E34356453E89 /* Pods-Runner.debug.xcconfig */, + 7255794ECF94B4FB91F39D79 /* Pods-Runner.release.xcconfig */, + 6E84AA1E5316F40ABCA87AF9 /* Pods-Runner.profile.xcconfig */, + 68E94AA7D5658C9B4705BC78 /* Pods-RunnerTests.debug.xcconfig */, + AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */, + 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 63A129979C19E770A95C46BB /* Pods_Runner.framework */, + 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 249AA0E568CF9FDCD7843723 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + D807BD7D820175A61286FA90 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 610737436CA1CAF7E249AF7E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -291,6 +323,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 249AA0E568CF9FDCD7843723 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +383,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 610737436CA1CAF7E249AF7E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D807BD7D820175A61286FA90 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +473,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 68E94AA7D5658C9B4705BC78 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +488,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +503,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index dadf3a801297..dd493f160dc7 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -16,7 +16,6 @@ dependencies: flutter: sdk: flutter mime: ^2.0.0 - video_player: ^2.8.6 dev_dependencies: flutter_test: From 644279bc01bb2574ac700bc121b917e81f9a05ae Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 14:18:36 -0500 Subject: [PATCH 145/398] macos runs --- packages/cross_file/cross_file/example/lib/main.dart | 4 ++-- packages/cross_file/cross_file_android/example/lib/main.dart | 4 ++-- packages/cross_file/cross_file_darwin/example/lib/main.dart | 4 ++-- .../example/macos/Runner.xcworkspace/contents.xcworkspacedata | 3 +++ .../example/macos/Runner/DebugProfile.entitlements | 2 ++ .../example/macos/Runner/Release.entitlements | 2 ++ 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index f6df294c1cba..29b1369ba4da 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -39,9 +39,9 @@ class FileOpenScreen extends StatelessWidget { debugPrint('File Last Modified: ${await file.lastModified()}'); return; } + } else { + debugPrint('No file selected.'); } - - debugPrint('No file selected.'); } Future _openDirectory() async { diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 09ed025084f3..13fe680aa7fa 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -47,9 +47,9 @@ class FileOpenScreen extends StatelessWidget { debugPrint('File Last Modified: ${await file.lastModified()}'); return; } + } else { + debugPrint('No file selected.'); } - - debugPrint('No file selected.'); } Future _openDirectory() async { diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 8545251fed60..4cb5359abbd0 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -39,9 +39,9 @@ class FileOpenScreen extends StatelessWidget { debugPrint('File Last Modified: ${await file.lastModified()}'); return; } + } else { + debugPrint('No file selected.'); } - - debugPrint('No file selected.'); } Future _openDirectory() async { diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements b/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements index dddb8a30c851..68acb49b6928 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/DebugProfile.entitlements @@ -8,5 +8,7 @@ com.apple.security.network.server + com.apple.security.files.user-selected.read-write + diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements b/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements index 852fa1a4728a..012d091fca66 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Release.entitlements @@ -4,5 +4,7 @@ com.apple.security.app-sandbox + com.apple.security.files.user-selected.read-write + From 94c3858eb469f0cd6839bcf7598aa26a278e74a2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 15:32:50 -0500 Subject: [PATCH 146/398] compiles on ios --- .../darwin/cross_file_darwin.podspec | 39 ++++++++----------- .../darwin/cross_file_darwin/Package.swift | 28 +++++++++++++ .../CrossFileDarwinApis.g.swift | 0 .../CrossFileDarwinPlugin.swift | 0 .../ProxyAPIRegistrar.swift | 0 .../Resources/PrivacyInfo.xcprivacy | 0 .../CrossFileDarwinApiImpl.swift | 0 .../FileHandleProxyAPIDelegate.swift | 0 8 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift rename packages/cross_file/cross_file_darwin/darwin/{Classes => cross_file_darwin/Sources/cross_file_darwin}/CrossFileDarwinApis.g.swift (100%) rename packages/cross_file/cross_file_darwin/darwin/{Classes => cross_file_darwin/Sources/cross_file_darwin}/CrossFileDarwinPlugin.swift (100%) rename packages/cross_file/cross_file_darwin/darwin/{Classes => cross_file_darwin/Sources/cross_file_darwin}/ProxyAPIRegistrar.swift (100%) rename packages/cross_file/cross_file_darwin/darwin/{ => cross_file_darwin/Sources/cross_file_darwin}/Resources/PrivacyInfo.xcprivacy (100%) rename packages/cross_file/cross_file_darwin/darwin/{Classes => cross_file_darwin/Sources/cross_file_darwin}/apiImplementations/CrossFileDarwinApiImpl.swift (100%) rename packages/cross_file/cross_file_darwin/darwin/{Classes => cross_file_darwin/Sources/cross_file_darwin}/apiImplementations/FileHandleProxyAPIDelegate.swift (100%) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec index 166ea7526ef1..2b40a208f48a 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec @@ -1,37 +1,30 @@ # # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint cross_file_darwin.podspec` to validate before publishing. # Pod::Spec.new do |s| s.name = 'cross_file_darwin' s.version = '0.0.1' - s.summary = 'A new Flutter plugin project.' + s.summary = 'A cross platform file Plugin for Flutter.' s.description = <<-DESC -A new Flutter plugin project. +A Flutter plugin that provides access to files. +Downloaded by pub (not CocoaPods). DESC - s.homepage = 'http://example.com' - s.license = { :file => '../LICENSE' } - s.author = { 'Your Company' => 'email@example.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - - # Set the deployment targets for both iOS and macOS. - s.ios.deployment_target = '13.0' - s.osx.deployment_target = '10.15' - - # Define the platform-specific dependencies. + s.homepage = 'https://github.com/flutter/packages' + s.license = { :type => 'BSD', :file => '../LICENSE' } + s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } + s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_darwin' } + s.documentation_url = 'https://pub.dev/packages/cross_file' + s.source_files = 'cross_file_darwin/Sources/cross_file_darwin/**/*.swift' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' - - # Flutter.framework does not contain a i386 slice, which is specific to iOS. + s.ios.deployment_target = '13.0' + s.osx.deployment_target = '10.15' + s.resource_bundles = {'cross_file_darwin_privacy' => ['cross_file_darwin/Sources/cross_file_darwin/Resources/PrivacyInfo.xcprivacy']} s.ios.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.osx.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } - + s.xcconfig = { + 'LIBRARY_SEARCH_PATHS' => '$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift', + 'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift', + } s.swift_version = '5.0' - - # If your plugin requires a privacy manifest, for example if it uses any - # required reason APIs, update the PrivacyInfo.xcprivacy file to describe your - # plugin's privacy impact, and then uncomment this line. For more information, - # see https://developer.apple.com/documentation/bundleresources/privacy_manifest_files - # s.resource_bundles = {'cross_file_darwin_privacy' => ['Resources/PrivacyInfo.xcprivacy']} end diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift new file mode 100644 index 000000000000..c3658d759b2c --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift @@ -0,0 +1,28 @@ +// swift-tools-version: 5.9 + +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import PackageDescription + +let package = Package( + name: "cross_file_darwin", + platforms: [ + .iOS("13.0"), + .macOS("10.15"), + ], + products: [ + .library(name: "cross-file-darwin", targets: ["cross_file_darwin"]) + ], + dependencies: [], + targets: [ + .target( + name: "cross_file_darwin", + dependencies: [], + resources: [ + .process("Resources") + ] + ) + ] +) diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift similarity index 100% rename from packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift similarity index 100% rename from packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinPlugin.swift rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift similarity index 100% rename from packages/cross_file/cross_file_darwin/darwin/Classes/ProxyAPIRegistrar.swift rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Resources/PrivacyInfo.xcprivacy b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/Resources/PrivacyInfo.xcprivacy similarity index 100% rename from packages/cross_file/cross_file_darwin/darwin/Resources/PrivacyInfo.xcprivacy rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/Resources/PrivacyInfo.xcprivacy diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift similarity index 100% rename from packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/CrossFileDarwinApiImpl.swift rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/FileHandleProxyAPIDelegate.swift similarity index 100% rename from packages/cross_file/cross_file_darwin/darwin/Classes/apiImplementations/FileHandleProxyAPIDelegate.swift rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/FileHandleProxyAPIDelegate.swift From 4841e6b97350680c45199424dfa7e4a30765393b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:02:22 -0500 Subject: [PATCH 147/398] export io impl --- packages/cross_file/cross_file_io/lib/cross_file_io.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 12b82d6e8335..4656879fad22 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -3,5 +3,5 @@ // found in the LICENSE file. export 'src/cross_file_io.dart'; -export 'src/io_cross_directory.dart' show IOXDirectoryCreationParams, IOXDirectoryExtension; -export 'src/io_cross_file.dart' show IOXFileCreationParams, IOXFileExtension; +export 'src/io_cross_directory.dart'; +export 'src/io_cross_file.dart'; From 1aee6e3485ae2c3c8030960e3e554602874dd819 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:28:44 -0500 Subject: [PATCH 148/398] update cross file to ask for start of scoped resource --- .../Classes/CrossFileDarwinApis.g.swift | 937 ++++++++++++++++++ .../CrossFileDarwinApiImpl.swift | 8 + .../lib/src/cross_file_darwin.dart | 14 + .../lib/src/cross_file_darwin_apis.g.dart | 349 ++++--- .../lib/src/darwin_cross_directory.dart | 59 ++ .../lib/src/darwin_cross_file.dart | 58 ++ .../lib/src/security_scoped_resource.dart | 14 + .../pigeons/cross_file_darwin_apis.dart | 8 + 8 files changed, 1268 insertions(+), 179 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift create mode 100644 packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart create mode 100644 packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift new file mode 100644 index 000000000000..3843f9385e22 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift @@ -0,0 +1,937 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.1.7), do not edit directly. +// See also: https://pub.dev/packages/pigeon + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +/// Error class for passing custom error details to Dart side. +final class PigeonError: Error { + let code: String + let message: String? + let details: Sendable? + + init(code: String, message: String?, details: Sendable?) { + self.code = code + self.message = message + self.details = details + } + + var localizedDescription: String { + return + "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" + } +} + +private func wrapResult(_ result: Any?) -> [Any?] { + return [result] +} + +private func wrapError(_ error: Any) -> [Any?] { + if let pigeonError = error as? PigeonError { + return [ + pigeonError.code, + pigeonError.message, + pigeonError.details, + ] + } + if let flutterError = error as? FlutterError { + return [ + flutterError.code, + flutterError.message, + flutterError.details, + ] + } + return [ + "\(error)", + "\(type(of: error))", + "Stacktrace: \(Thread.callStackSymbols)", + ] +} + +private func createConnectionError(withChannelName channelName: String) -> PigeonError { + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") +} + +private func isNullish(_ value: Any?) -> Bool { + return value is NSNull || value == nil +} + +private func nilOrValue(_ value: Any?) -> T? { + if value is NSNull { return nil } + return value as! T? +} + +func deepEqualsCrossFileDarwinApis(_ lhs: Any?, _ rhs: Any?) -> Bool { + let cleanLhs = nilOrValue(lhs) as Any? + let cleanRhs = nilOrValue(rhs) as Any? + switch (cleanLhs, cleanRhs) { + case (nil, nil): + return true + + case (nil, _), (_, nil): + return false + + case is (Void, Void): + return true + + case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): + return cleanLhsHashable == cleanRhsHashable + + case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): + guard cleanLhsArray.count == cleanRhsArray.count else { return false } + for (index, element) in cleanLhsArray.enumerated() { + if !deepEqualsCrossFileDarwinApis(element, cleanRhsArray[index]) { + return false + } + } + return true + + case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): + guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } + for (key, cleanLhsValue) in cleanLhsDictionary { + guard cleanRhsDictionary.index(forKey: key) != nil else { return false } + if !deepEqualsCrossFileDarwinApis(cleanLhsValue, cleanRhsDictionary[key]!) { + return false + } + } + return true + + default: + // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue. + return false + } +} + +func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { + if let valueList = value as? [AnyHashable] { + for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } + return + } + + if let valueDict = value as? [AnyHashable: AnyHashable] { + for key in valueDict.keys { + hasher.combine(key) + deepHashCrossFileDarwinApis(value: valueDict[key]!, hasher: &hasher) + } + return + } + + if let hashableValue = value as? AnyHashable { + hasher.combine(hashableValue.hashValue) + } + + return hasher.combine(String(describing: value)) +} + + +/// Handles the callback when an object is deallocated. +protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { + /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. + func onDeinit(identifier: Int64) +} + + +// Attaches to an object to receive a callback when the object is deallocated. +internal final class CrossFileDarwinApisPigeonInternalFinalizer { + internal static let associatedObjectKey = malloc(1)! + + private let identifier: Int64 + // Reference to the delegate is weak because the callback should be ignored if the + // `InstanceManager` is deallocated. + internal weak var delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate? + + private init(identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { + self.identifier = identifier + self.delegate = delegate + } + + internal static func attach( + to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + ) { + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) + } + + static func detach(from instance: AnyObject) { + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + if let finalizer = finalizer { + finalizer.delegate = nil + objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) + } + } + + deinit { + delegate?.onDeinit(identifier: identifier) + } +} + + +/// Maintains instances used to communicate with the corresponding objects in Dart. +/// +/// Objects stored in this container are represented by an object in Dart that is also stored in +/// an InstanceManager with the same identifier. +/// +/// When an instance is added with an identifier, either can be used to retrieve the other. +/// +/// Added instances are added as a weak reference and a strong reference. When the strong +/// reference is removed and the weak reference is deallocated,`CrossFileDarwinApisPigeonInternalFinalizerDelegate.onDeinit` +/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is +/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), +/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually +/// again. +/// +/// Accessing and inserting to an InstanceManager is thread safe. +final class CrossFileDarwinApisPigeonInstanceManager { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private static let minHostCreatedIdentifier: Int64 = 65536 + + private let lockQueue = DispatchQueue(label: "CrossFileDarwinApisPigeonInstanceManager") + private let identifiers: NSMapTable = NSMapTable( + keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) + private let weakInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) + private let strongInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) + private let finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + private var nextIdentifier: Int64 = minHostCreatedIdentifier + + public init(finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { + self.finalizerDelegate = finalizerDelegate + } + + /// Adds a new instance that was instantiated from Dart. + /// + /// The same instance can be added multiple times, but each identifier must be unique. This allows + /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. + /// + /// - Parameters: + /// - instance: the instance to be stored + /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique + func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + lockQueue.async { + self.addInstance(instance, withIdentifier: identifier) + } + } + + /// Adds a new instance that was instantiated from the host platform. + /// + /// - Parameters: + /// - instance: the instance to be stored. This must be unique to all other added instances. + /// - Returns: the unique identifier (>= 0) stored with instance + func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { + assert(!containsInstance(instance), "Instance of \(instance) has already been added.") + var identifier: Int64 = -1 + lockQueue.sync { + identifier = nextIdentifier + nextIdentifier += 1 + self.addInstance(instance, withIdentifier: identifier) + } + return identifier + } + + /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier paired to an instance. + /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if + /// the manager doesn't contain the value + func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) + strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + /// Retrieves the instance associated with identifier. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier associated with an instance + /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func instance(forIdentifier instanceIdentifier: Int64) -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + assert(identifier >= 0) + assert( + weakInstances.object(forKey: identifier as NSNumber) == nil, + "Identifier has already been added: \(identifier)") + identifiers.setObject(NSNumber(value: identifier), forKey: instance) + weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) + strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) + CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + } + + /// Retrieves the identifier paired with an instance. + /// + /// If the manager contains a strong reference to `instance`, it will return the identifier + /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new + /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. + /// + /// If this method returns a nonnull identifier, this method also expects the Dart + /// `CrossFileDarwinApisPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + /// identifier is associated with. + /// + /// - Parameters: + /// - instance: an instance that may be stored in the manager + /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { + var identifier: Int64? = nil + lockQueue.sync { + if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { + strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) + identifier = existingIdentifier + } + } + return identifier + } + + /// Whether this manager contains the given `instance`. + /// + /// - Parameters: + /// - instance: the instance whose presence in this manager is to be tested + /// - Returns: whether this manager contains the given `instance` + func containsInstance(_ instance: AnyObject) -> Bool { + var containsInstance = false + lockQueue.sync { + containsInstance = identifiers.object(forKey: instance) != nil + } + return containsInstance + } + + /// Removes all of the instances from this manager. + /// + /// The manager will be empty after this call returns. + func removeAllObjects() throws { + lockQueue.sync { + let weakInstancesEnumerator = weakInstances.objectEnumerator()! + while let instance = weakInstancesEnumerator.nextObject() { + CrossFileDarwinApisPigeonInternalFinalizer.detach(from: instance as AnyObject) + } + identifiers.removeAllObjects() + weakInstances.removeAllObjects() + strongInstances.removeAllObjects() + nextIdentifier = CrossFileDarwinApisPigeonInstanceManager.minHostCreatedIdentifier + } + } + + /// The number of instances stored as a strong reference. + /// + /// For debugging and testing purposes. + internal var strongInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = strongInstances.count + } + return count + } + + /// The number of instances stored as a weak reference. + /// + /// For debugging and testing purposes. NSMapTables that store keys or objects as weak + /// reference will be reclaimed non-deterministically. + internal var weakInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = weakInstances.count + } + return count + } +} + + +private class CrossFileDarwinApisPigeonInstanceManagerApi { + /// The codec used for serializing messages. + var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } + + /// Handles sending and receiving messages with Dart. + unowned let binaryMessenger: FlutterBinaryMessenger + + init(binaryMessenger: FlutterBinaryMessenger) { + self.binaryMessenger = binaryMessenger + } + + /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + let codec = CrossFileDarwinApisPigeonCodec.shared + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + removeStrongReferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! Int64 + do { + let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeStrongReferenceChannel.setMessageHandler(nil) + } + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + clearChannel.setMessageHandler { _, reply in + do { + try instanceManager.removeAllObjects() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearChannel.setMessageHandler(nil) + } + } + + /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([identifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } +} +protocol CrossFileDarwinApisPigeonProxyApiDelegate { + /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of + /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle +} + +open class CrossFileDarwinApisPigeonProxyApiRegistrar { + let binaryMessenger: FlutterBinaryMessenger + let apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + let instanceManager: CrossFileDarwinApisPigeonInstanceManager + /// Whether APIs should ignore calling to Dart. + public var ignoreCallsToDart = false + private var _codec: FlutterStandardMessageCodec? + var codec: FlutterStandardMessageCodec { + if _codec == nil { + _codec = FlutterStandardMessageCodec( + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + } + return _codec! + } + + private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + let api: CrossFileDarwinApisPigeonInstanceManagerApi + + init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { + self.api = api + } + + public func onDeinit(identifier: Int64) { + api.removeStrongReference(identifier: identifier) { + _ in + } + } + } + + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + self.binaryMessenger = binaryMessenger + self.apiDelegate = apiDelegate + self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( + finalizerDelegate: InstanceManagerApiFinalizerDelegate( + CrossFileDarwinApisPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) + } + + func setUp() { + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + } + func tearDown() { + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + } +} +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + let identifier = self.readValue() + let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( + forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) + if instance == nil { + print("Failed to find instance with identifier: \(identifier!)") + } + return instance + default: + return super.readValue(ofType: type) + } + } + } + + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func writeValue(_ value: Any) { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + super.writeValue(value) + return + } + + + if let instance = value as? FileHandle { + pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + { + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) + } else { + print("Unsupported value: \(value) of \(type(of: value))") + assert(false, "Unsupported value for CrossFileDarwinApisPigeonInternalProxyApiCodecWriter") + } + + } + } + + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + } + + override func reader(with data: Data) -> FlutterStandardReader { + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + } +} + +/// Result of a call to `CrossFileDarwinApi.fileExists`. +/// +/// Generated class from Pigeon that represents data sent in messages. +struct FileExistsResult: Hashable { + /// Whether the file exists. + var exists: Bool + /// Whether th + var isDirectory: Bool + + + // swift-format-ignore: AlwaysUseLowerCamelCase + static func fromList(_ pigeonVar_list: [Any?]) -> FileExistsResult? { + let exists = pigeonVar_list[0] as! Bool + let isDirectory = pigeonVar_list[1] as! Bool + + return FileExistsResult( + exists: exists, + isDirectory: isDirectory + ) + } + func toList() -> [Any?] { + return [ + exists, + isDirectory, + ] + } + static func == (lhs: FileExistsResult, rhs: FileExistsResult) -> Bool { + return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) } + func hash(into hasher: inout Hasher) { + deepHashCrossFileDarwinApis(value: toList(), hasher: &hasher) + } +} + +private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 129: + return FileExistsResult.fromList(self.readValue() as! [Any?]) + default: + return super.readValue(ofType: type) + } + } +} + +private class CrossFileDarwinApisPigeonCodecWriter: FlutterStandardWriter { + override func writeValue(_ value: Any) { + if let value = value as? FileExistsResult { + super.writeByte(129) + super.writeValue(value.toList()) + } else { + super.writeValue(value) + } + } +} + +private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderWriter { + override func reader(with data: Data) -> FlutterStandardReader { + return CrossFileDarwinApisPigeonCodecReader(data: data) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return CrossFileDarwinApisPigeonCodecWriter(data: data) + } +} + +class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) +} + +/// Api for getting access to file information. +/// +/// Generated protocol from Pigeon that represents a handler of messages from Flutter. +protocol CrossFileDarwinApi { + /// Attempt to create a bookmarked URL that serves as a persistent reference + /// to a file. + func tryCreateBookmarkedUrl(url: String) throws -> String? + /// Whether the invoking object appears able to read a specified file. + func isReadableFile(url: String) throws -> Bool + /// Whether a file or directory exists at a specified path. + func fileExists(url: String) throws -> FileExistsResult + /// The file’s last modified date in milliseconds since epoch. + func fileModificationDate(url: String) throws -> Int64? + /// The file’s size in bytes. + func fileSize(url: String) throws -> Int64? + /// Performs a shallow search of the specified directory and returns the paths + /// of any contained items. + func list(url: String) throws -> [String] + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + func startAccessingSecurityScopedResource(url: String) throws -> Bool + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + func stopAccessingSecurityScopedResource(url: String) throws +} + +/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. +class CrossFileDarwinApiSetup { + static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } + /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { + let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" + /// Attempt to create a bookmarked URL that serves as a persistent reference + /// to a file. + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.tryCreateBookmarkedUrl(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + tryCreateBookmarkedUrlChannel.setMessageHandler(nil) + } + /// Whether the invoking object appears able to read a specified file. + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isReadableFileChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.isReadableFile(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isReadableFileChannel.setMessageHandler(nil) + } + /// Whether a file or directory exists at a specified path. + let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileExistsChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileExists(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileExistsChannel.setMessageHandler(nil) + } + /// The file’s last modified date in milliseconds since epoch. + let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileModificationDateChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileModificationDate(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileModificationDateChannel.setMessageHandler(nil) + } + /// The file’s size in bytes. + let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + fileSizeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.fileSize(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + fileSizeChannel.setMessageHandler(nil) + } + /// Performs a shallow search of the specified directory and returns the paths + /// of any contained items. + let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + listChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.list(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + listChannel.setMessageHandler(nil) + } + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.startAccessingSecurityScopedResource(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + } + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + try api.stopAccessingSecurityScopedResource(url: urlArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + } + } +} +protocol PigeonApiDelegateFileHandle { + /// Returns a file handle initialized for reading the file, device, or named + /// socket at the specified path. + func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? + /// Reads data synchronously up to the specified number of bytes. + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? + /// Reads the available data synchronously up to the end of file or maximum + /// number of bytes. + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? + /// Moves the file pointer to the specified offset within the file. + func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws + /// Disallows further access to the represented file or communications channel + /// and signals end of file on communications channels that permit writing. + func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws +} + +protocol PigeonApiProtocolFileHandle { +} + +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateFileHandle + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let forReadingAtPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + forReadingAtPathChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pathArg = args[0] as! String + do { + let result = try api.pigeonDelegate.forReadingAtPath(pigeonApi: api, path: pathArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + forReadingAtPathChannel.setMessageHandler(nil) + } + let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + readUpToCountChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + let countArg = args[1] as! Int64 + do { + let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + readUpToCountChannel.setMessageHandler(nil) + } + let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + readToEndChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + do { + let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + readToEndChannel.setMessageHandler(nil) + } + let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + seekChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + let offsetArg = args[1] as! Int64 + do { + try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + seekChannel.setMessageHandler(nil) + } + let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + closeChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let pigeonInstanceArg = args[0] as! FileHandle + do { + try api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: pigeonInstanceArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + closeChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 1372a8736a9b..cf0c38fd75e2 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -77,4 +77,12 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { func list(url: String) throws -> [String] { return try fileManager.contentsOfDirectory(atPath: url) } + + func startAccessingSecurityScopedResource(url: String) throws -> Bool { + return URL(fileURLWithPath: url).startAccessingSecurityScopedResource() + } + + func stopAccessingSecurityScopedResource(url: String) throws { + URL(fileURLWithPath: url).stopAccessingSecurityScopedResource() + } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index f00f2dc02852..47c06b0b6807 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -5,6 +5,8 @@ import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'darwin_cross_directory.dart'; +import 'darwin_cross_file.dart'; import 'darwin_scoped_storage_cross_directory.dart'; import 'darwin_scoped_storage_cross_file.dart'; @@ -15,6 +17,18 @@ base class CrossFileDarwin extends CrossFileIO { CrossFilePlatform.instance = CrossFileDarwin(); } + @override + DarwinXFile createPlatformXFile(PlatformXFileCreationParams params) { + return DarwinXFile(params); + } + + @override + DarwinXDirectory createPlatformXDirectory( + PlatformXDirectoryCreationParams params, + ) { + return DarwinXDirectory(params); + } + @override DarwinScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index d682c5bf6ae2..56424ffef5bf 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.5), do not edit directly. +// Autogenerated from Pigeon (v26.1.7), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers @@ -9,8 +9,7 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' - show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -21,11 +20,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -34,21 +29,16 @@ List wrapResponse({ } return [error.code, error.message, error.details]; } - bool _deepEquals(Object? a, Object? b) { if (a is List && b is List) { return a.length == b.length && - a.indexed.every( - ((int, dynamic) item) => _deepEquals(item.$2, b[item.$1]), - ); + a.indexed + .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); } if (a is Map && b is Map) { - return a.length == b.length && - a.entries.every( - (MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key]), - ); + return a.length == b.length && a.entries.every((MapEntry entry) => + (b as Map).containsKey(entry.key) && + _deepEquals(entry.value, b[entry.key])); } return a == b; } @@ -83,7 +73,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -153,10 +143,9 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> - _weakInstances = >{}; - final Map _strongInstances = - {}; + final Map> _weakInstances = + >{}; + final Map _strongInstances = {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -169,8 +158,7 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = - _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -178,12 +166,8 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers( - instanceManager: instanceManager, - ); - FileHandle.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -200,9 +184,8 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference( - instance, - ); + _weakInstances[identifier] = + WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -263,21 +246,15 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference( - int identifier, - ) { - final PigeonInternalProxyApiBaseClass? weakInstance = - _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = - _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance - .pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = - WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -299,10 +276,7 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance( - PigeonInternalProxyApiBaseClass instance, - int identifier, - ) { + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -331,7 +305,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -344,35 +318,28 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert( - arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', - ); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); try { - (instanceManager ?? PigeonInstanceManager.instance).remove( - arg_identifier!, - ); + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -387,9 +354,8 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -432,34 +398,36 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference( - readValue(buffer)! as int, - ); - default: - return super.readValueOfType(type, buffer); - } - } + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } } + /// Result of a call to `CrossFileDarwinApi.fileExists`. class FileExistsResult { - FileExistsResult({required this.exists, required this.isDirectory}); + FileExistsResult({ + required this.exists, + required this.isDirectory, + }); /// Whether the file exists. bool exists; @@ -468,12 +436,14 @@ class FileExistsResult { bool isDirectory; List _toList() { - return [exists, isDirectory]; + return [ + exists, + isDirectory, + ]; } Object encode() { - return _toList(); - } + return _toList(); } static FileExistsResult decode(Object result) { result as List; @@ -497,9 +467,11 @@ class FileExistsResult { @override // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()); + int get hashCode => Object.hashAll(_toList()) +; } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -507,7 +479,7 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileExistsResult) { + } else if (value is FileExistsResult) { buffer.putUint8(129); writeValue(buffer, value.encode()); } else { @@ -518,7 +490,7 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: + case 129: return FileExistsResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); @@ -526,17 +498,14 @@ class _PigeonCodec extends StandardMessageCodec { } } +/// Api for getting access to file information. class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({ - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty - ? '.$messageChannelSuffix' - : ''; + CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -546,16 +515,13 @@ class CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -572,16 +538,13 @@ class CrossFileDarwinApi { /// Whether the invoking object appears able to read a specified file. Future isReadableFile(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -603,16 +566,13 @@ class CrossFileDarwinApi { /// Whether a file or directory exists at a specified path. Future fileExists(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -632,18 +592,15 @@ class CrossFileDarwinApi { } } - /// The file’s last modified date. + /// The file’s last modified date in milliseconds since epoch. Future fileModificationDate(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -660,16 +617,13 @@ class CrossFileDarwinApi { /// The file’s size in bytes. Future fileSize(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -687,16 +641,13 @@ class CrossFileDarwinApi { /// Performs a shallow search of the specified directory and returns the paths /// of any contained items. Future> list(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -715,8 +666,60 @@ class CrossFileDarwinApi { return (pigeonVar_replyList[0] as List?)!.cast(); } } -} + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + Future startAccessingSecurityScopedResource(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } + + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + Future stopAccessingSecurityScopedResource(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } +} /// An object-oriented wrapper for a file descriptor. /// /// See https://developer.apple.com/documentation/foundation/filehandle. @@ -742,46 +745,39 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert( - message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.', - ); + assert(message != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.'); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert( - arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.', - ); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.'); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + FileHandle.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -800,8 +796,7 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { } final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath'; @@ -810,9 +805,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [path], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([path]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -839,9 +833,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, count], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, count]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -869,9 +862,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -898,9 +890,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, offset], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, offset]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -928,9 +919,8 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -953,3 +943,4 @@ class FileHandle extends PigeonInternalProxyApiBaseClass { ); } } + diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart new file mode 100644 index 000000000000..133ae4c3ef7f --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart @@ -0,0 +1,59 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; + +import 'cross_file_darwin_apis.g.dart'; +import 'security_scoped_resource.dart'; + +/// Implementation of [PlatformXDirectoryCreationParams] for iOS and +/// macOS. +@immutable +base class DarwinXDirectoryCreationParams extends IOXDirectoryCreationParams { + /// Constructs a [DarwinXDirectoryCreationParams]. + DarwinXDirectoryCreationParams({ + required super.uri, + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(); + + /// The API used to call to native code to interact with files. + @visibleForTesting + final CrossFileDarwinApi api; +} + +/// Implementation of [PlatformXDirectory] for iOS and macOS. +base class DarwinXDirectory extends IOXDirectory + with DarwinXDirectoryExtension { + /// Constructs a [DarwinXDirectory]. + DarwinXDirectory(super.params) : super(); + + late final DarwinXDirectoryCreationParams _params = + super.params is DarwinXDirectoryCreationParams + ? super.params as DarwinXDirectoryCreationParams + : DarwinXDirectoryCreationParams(uri: super.params.uri); + + @override + DarwinXDirectoryCreationParams get params => _params; + + @override + DarwinXDirectoryExtension? get extension => this; + + @override + Future startAccessingSecurityScopedResource() { + return params.api.startAccessingSecurityScopedResource(params.uri); + } + + @override + Future stopAccessingSecurityScopedResource() { + return params.api.stopAccessingSecurityScopedResource(params.uri); + } +} + +/// Provides platform specific features for [DarwinXDirectory]. +mixin DarwinXDirectoryExtension + implements IOXDirectoryExtension, SecurityScopedResource {} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart new file mode 100644 index 000000000000..d6027c29217e --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart @@ -0,0 +1,58 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart'; + +import 'cross_file_darwin_apis.g.dart'; +import 'security_scoped_resource.dart'; + +/// Implementation of [PlatformXFileCreationParams] for iOS and +/// macOS. +@immutable +base class DarwinXFileCreationParams extends IOXFileCreationParams { + /// Constructs a [DarwinXFileCreationParams]. + DarwinXFileCreationParams({ + required super.uri, + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(); + + /// The API used to call to native code to interact with files. + @visibleForTesting + final CrossFileDarwinApi api; +} + +/// Implementation of [PlatformXFile] for iOS and macOS. +base class DarwinXFile extends IOXFile with DarwinXFileExtension { + /// Constructs a [DarwinXFile]. + DarwinXFile(super.params) : super(); + + late final DarwinXFileCreationParams _params = + super.params is DarwinXFileCreationParams + ? super.params as DarwinXFileCreationParams + : DarwinXFileCreationParams(uri: super.params.uri); + + @override + DarwinXFileCreationParams get params => _params; + + @override + DarwinXFileExtension? get extension => this; + + @override + Future startAccessingSecurityScopedResource() { + return params.api.startAccessingSecurityScopedResource(params.uri); + } + + @override + Future stopAccessingSecurityScopedResource() { + return params.api.stopAccessingSecurityScopedResource(params.uri); + } +} + +/// Provides platform specific features for [DarwinXFile]. +mixin DarwinXFileExtension + implements IOXFileExtension, SecurityScopedResource {} diff --git a/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart b/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart new file mode 100644 index 000000000000..66b3aa632e83 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart @@ -0,0 +1,14 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// Common methods for interacting with a security-scoped URL. +mixin SecurityScopedResource { + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + Future startAccessingSecurityScopedResource(); + + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + Future stopAccessingSecurityScopedResource(); +} diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index 2ee362f1f47d..a0738011f7eb 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -44,6 +44,14 @@ abstract class CrossFileDarwinApi { /// Performs a shallow search of the specified directory and returns the paths /// of any contained items. List list(String url); + + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + bool startAccessingSecurityScopedResource(String url); + + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + void stopAccessingSecurityScopedResource(String url); } /// An object-oriented wrapper for a file descriptor. From bbbc10fdbc517721b3a942d300d3f5a1ee94dace Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 16:30:36 -0500 Subject: [PATCH 149/398] export new files --- .../cross_file/cross_file_darwin/lib/cross_file_darwin.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index f3c6d80e9f10..5a2961bfce29 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -6,7 +6,8 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXFileEntity; export 'src/cross_file_darwin.dart'; - +export 'src/darwin_cross_directory.dart' show DarwinXDirectoryExtension; +export 'src/darwin_cross_file.dart' show DarwinXFileExtension; export 'src/darwin_scoped_storage_cross_directory.dart' show DarwinScopedStorageXDirectoryExtension; export 'src/darwin_scoped_storage_cross_file.dart' From 9029901b853779aa081ea6f64b986f6e00618b25 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:30:02 -0500 Subject: [PATCH 150/398] fix code gen --- .../Classes/CrossFileDarwinApis.g.swift | 937 ------------------ .../CrossFileDarwinApis.g.swift | 254 ++--- .../pigeons/cross_file_darwin_apis.dart | 3 +- 3 files changed, 111 insertions(+), 1083 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift deleted file mode 100644 index 3843f9385e22..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Classes/CrossFileDarwinApis.g.swift +++ /dev/null @@ -1,937 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.7), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Sendable? - - init(code: String, message: String?, details: Sendable?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -func deepEqualsCrossFileDarwinApis(_ lhs: Any?, _ rhs: Any?) -> Bool { - let cleanLhs = nilOrValue(lhs) as Any? - let cleanRhs = nilOrValue(rhs) as Any? - switch (cleanLhs, cleanRhs) { - case (nil, nil): - return true - - case (nil, _), (_, nil): - return false - - case is (Void, Void): - return true - - case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): - return cleanLhsHashable == cleanRhsHashable - - case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): - guard cleanLhsArray.count == cleanRhsArray.count else { return false } - for (index, element) in cleanLhsArray.enumerated() { - if !deepEqualsCrossFileDarwinApis(element, cleanRhsArray[index]) { - return false - } - } - return true - - case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } - for (key, cleanLhsValue) in cleanLhsDictionary { - guard cleanRhsDictionary.index(forKey: key) != nil else { return false } - if !deepEqualsCrossFileDarwinApis(cleanLhsValue, cleanRhsDictionary[key]!) { - return false - } - } - return true - - default: - // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue. - return false - } -} - -func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { - if let valueList = value as? [AnyHashable] { - for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } - return - } - - if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { - hasher.combine(key) - deepHashCrossFileDarwinApis(value: valueDict[key]!, hasher: &hasher) - } - return - } - - if let hashableValue = value as? AnyHashable { - hasher.combine(hashableValue.hashValue) - } - - return hasher.combine(String(describing: value)) -} - - -/// Handles the callback when an object is deallocated. -protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { - /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. - func onDeinit(identifier: Int64) -} - - -// Attaches to an object to receive a callback when the object is deallocated. -internal final class CrossFileDarwinApisPigeonInternalFinalizer { - internal static let associatedObjectKey = malloc(1)! - - private let identifier: Int64 - // Reference to the delegate is weak because the callback should be ignored if the - // `InstanceManager` is deallocated. - internal weak var delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate? - - private init(identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { - self.identifier = identifier - self.delegate = delegate - } - - internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate - ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) - objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) - } - - static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer - if let finalizer = finalizer { - finalizer.delegate = nil - objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) - } - } - - deinit { - delegate?.onDeinit(identifier: identifier) - } -} - - -/// Maintains instances used to communicate with the corresponding objects in Dart. -/// -/// Objects stored in this container are represented by an object in Dart that is also stored in -/// an InstanceManager with the same identifier. -/// -/// When an instance is added with an identifier, either can be used to retrieve the other. -/// -/// Added instances are added as a weak reference and a strong reference. When the strong -/// reference is removed and the weak reference is deallocated,`CrossFileDarwinApisPigeonInternalFinalizerDelegate.onDeinit` -/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is -/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), -/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually -/// again. -/// -/// Accessing and inserting to an InstanceManager is thread safe. -final class CrossFileDarwinApisPigeonInstanceManager { - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously from Dart. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - private static let minHostCreatedIdentifier: Int64 = 65536 - - private let lockQueue = DispatchQueue(label: "CrossFileDarwinApisPigeonInstanceManager") - private let identifiers: NSMapTable = NSMapTable( - keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) - private let weakInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) - private let strongInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) - private let finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate - private var nextIdentifier: Int64 = minHostCreatedIdentifier - - public init(finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { - self.finalizerDelegate = finalizerDelegate - } - - /// Adds a new instance that was instantiated from Dart. - /// - /// The same instance can be added multiple times, but each identifier must be unique. This allows - /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. - /// - /// - Parameters: - /// - instance: the instance to be stored - /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique - func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - lockQueue.async { - self.addInstance(instance, withIdentifier: identifier) - } - } - - /// Adds a new instance that was instantiated from the host platform. - /// - /// - Parameters: - /// - instance: the instance to be stored. This must be unique to all other added instances. - /// - Returns: the unique identifier (>= 0) stored with instance - func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { - assert(!containsInstance(instance), "Instance of \(instance) has already been added.") - var identifier: Int64 = -1 - lockQueue.sync { - identifier = nextIdentifier - nextIdentifier += 1 - self.addInstance(instance, withIdentifier: identifier) - } - return identifier - } - - /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier paired to an instance. - /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if - /// the manager doesn't contain the value - func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) - strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - /// Retrieves the instance associated with identifier. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier associated with an instance - /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func instance(forIdentifier instanceIdentifier: Int64) -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - assert(identifier >= 0) - assert( - weakInstances.object(forKey: identifier as NSNumber) == nil, - "Identifier has already been added: \(identifier)") - identifiers.setObject(NSNumber(value: identifier), forKey: instance) - weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) - strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) - } - - /// Retrieves the identifier paired with an instance. - /// - /// If the manager contains a strong reference to `instance`, it will return the identifier - /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new - /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. - /// - /// If this method returns a nonnull identifier, this method also expects the Dart - /// `CrossFileDarwinApisPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - /// identifier is associated with. - /// - /// - Parameters: - /// - instance: an instance that may be stored in the manager - /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { - var identifier: Int64? = nil - lockQueue.sync { - if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { - strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) - identifier = existingIdentifier - } - } - return identifier - } - - /// Whether this manager contains the given `instance`. - /// - /// - Parameters: - /// - instance: the instance whose presence in this manager is to be tested - /// - Returns: whether this manager contains the given `instance` - func containsInstance(_ instance: AnyObject) -> Bool { - var containsInstance = false - lockQueue.sync { - containsInstance = identifiers.object(forKey: instance) != nil - } - return containsInstance - } - - /// Removes all of the instances from this manager. - /// - /// The manager will be empty after this call returns. - func removeAllObjects() throws { - lockQueue.sync { - let weakInstancesEnumerator = weakInstances.objectEnumerator()! - while let instance = weakInstancesEnumerator.nextObject() { - CrossFileDarwinApisPigeonInternalFinalizer.detach(from: instance as AnyObject) - } - identifiers.removeAllObjects() - weakInstances.removeAllObjects() - strongInstances.removeAllObjects() - nextIdentifier = CrossFileDarwinApisPigeonInstanceManager.minHostCreatedIdentifier - } - } - - /// The number of instances stored as a strong reference. - /// - /// For debugging and testing purposes. - internal var strongInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = strongInstances.count - } - return count - } - - /// The number of instances stored as a weak reference. - /// - /// For debugging and testing purposes. NSMapTables that store keys or objects as weak - /// reference will be reclaimed non-deterministically. - internal var weakInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = weakInstances.count - } - return count - } -} - - -private class CrossFileDarwinApisPigeonInstanceManagerApi { - /// The codec used for serializing messages. - var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } - - /// Handles sending and receiving messages with Dart. - unowned let binaryMessenger: FlutterBinaryMessenger - - init(binaryMessenger: FlutterBinaryMessenger) { - self.binaryMessenger = binaryMessenger - } - - /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { - let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - removeStrongReferenceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! Int64 - do { - let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - removeStrongReferenceChannel.setMessageHandler(nil) - } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - clearChannel.setMessageHandler { _, reply in - do { - try instanceManager.removeAllObjects() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - clearChannel.setMessageHandler(nil) - } - } - - /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([identifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } -} -protocol CrossFileDarwinApisPigeonProxyApiDelegate { - /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of - /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle -} - -open class CrossFileDarwinApisPigeonProxyApiRegistrar { - let binaryMessenger: FlutterBinaryMessenger - let apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - let instanceManager: CrossFileDarwinApisPigeonInstanceManager - /// Whether APIs should ignore calling to Dart. - public var ignoreCallsToDart = false - private var _codec: FlutterStandardMessageCodec? - var codec: FlutterStandardMessageCodec { - if _codec == nil { - _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) - } - return _codec! - } - - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { - let api: CrossFileDarwinApisPigeonInstanceManagerApi - - init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { - self.api = api - } - - public func onDeinit(identifier: Int64) { - api.removeStrongReference(identifier: identifier) { - _ in - } - } - } - - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { - self.binaryMessenger = binaryMessenger - self.apiDelegate = apiDelegate - self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( - finalizerDelegate: InstanceManagerApiFinalizerDelegate( - CrossFileDarwinApisPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) - } - - func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) - } - func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - } -} -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 128: - let identifier = self.readValue() - let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( - forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) - if instance == nil { - print("Failed to find instance with identifier: \(identifier!)") - } - return instance - default: - return super.readValue(ofType: type) - } - } - } - - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { - super.writeValue(value) - return - } - - - if let instance = value as? FileHandle { - pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) - return - } - - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) - { - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) - } else { - print("Unsupported value: \(value) of \(type(of: value))") - assert(false, "Unsupported value for CrossFileDarwinApisPigeonInternalProxyApiCodecWriter") - } - - } - } - - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - } - - override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) - } -} - -/// Result of a call to `CrossFileDarwinApi.fileExists`. -/// -/// Generated class from Pigeon that represents data sent in messages. -struct FileExistsResult: Hashable { - /// Whether the file exists. - var exists: Bool - /// Whether th - var isDirectory: Bool - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> FileExistsResult? { - let exists = pigeonVar_list[0] as! Bool - let isDirectory = pigeonVar_list[1] as! Bool - - return FileExistsResult( - exists: exists, - isDirectory: isDirectory - ) - } - func toList() -> [Any?] { - return [ - exists, - isDirectory, - ] - } - static func == (lhs: FileExistsResult, rhs: FileExistsResult) -> Bool { - return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) } - func hash(into hasher: inout Hasher) { - deepHashCrossFileDarwinApis(value: toList(), hasher: &hasher) - } -} - -private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - return FileExistsResult.fromList(self.readValue() as! [Any?]) - default: - return super.readValue(ofType: type) - } - } -} - -private class CrossFileDarwinApisPigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? FileExistsResult { - super.writeByte(129) - super.writeValue(value.toList()) - } else { - super.writeValue(value) - } - } -} - -private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonCodecWriter(data: data) - } -} - -class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) -} - -/// Api for getting access to file information. -/// -/// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol CrossFileDarwinApi { - /// Attempt to create a bookmarked URL that serves as a persistent reference - /// to a file. - func tryCreateBookmarkedUrl(url: String) throws -> String? - /// Whether the invoking object appears able to read a specified file. - func isReadableFile(url: String) throws -> Bool - /// Whether a file or directory exists at a specified path. - func fileExists(url: String) throws -> FileExistsResult - /// The file’s last modified date in milliseconds since epoch. - func fileModificationDate(url: String) throws -> Int64? - /// The file’s size in bytes. - func fileSize(url: String) throws -> Int64? - /// Performs a shallow search of the specified directory and returns the paths - /// of any contained items. - func list(url: String) throws -> [String] - /// In an app that has adopted App Sandbox, makes the resource pointed to by a - /// security-scoped URL available to the app. - func startAccessingSecurityScopedResource(url: String) throws -> Bool - /// In an app that adopts App Sandbox, revokes access to the resource pointed - /// to by a security-scoped URL. - func stopAccessingSecurityScopedResource(url: String) throws -} - -/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class CrossFileDarwinApiSetup { - static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } - /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { - let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - /// Attempt to create a bookmarked URL that serves as a persistent reference - /// to a file. - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.tryCreateBookmarkedUrl(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - tryCreateBookmarkedUrlChannel.setMessageHandler(nil) - } - /// Whether the invoking object appears able to read a specified file. - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isReadableFileChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.isReadableFile(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isReadableFileChannel.setMessageHandler(nil) - } - /// Whether a file or directory exists at a specified path. - let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileExistsChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileExists(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileExistsChannel.setMessageHandler(nil) - } - /// The file’s last modified date in milliseconds since epoch. - let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileModificationDateChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileModificationDate(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileModificationDateChannel.setMessageHandler(nil) - } - /// The file’s size in bytes. - let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileSizeChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileSize(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileSizeChannel.setMessageHandler(nil) - } - /// Performs a shallow search of the specified directory and returns the paths - /// of any contained items. - let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - listChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.list(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - listChannel.setMessageHandler(nil) - } - /// In an app that has adopted App Sandbox, makes the resource pointed to by a - /// security-scoped URL available to the app. - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.startAccessingSecurityScopedResource(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) - } - /// In an app that adopts App Sandbox, revokes access to the resource pointed - /// to by a security-scoped URL. - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - try api.stopAccessingSecurityScopedResource(url: urlArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) - } - } -} -protocol PigeonApiDelegateFileHandle { - /// Returns a file handle initialized for reading the file, device, or named - /// socket at the specified path. - func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? - /// Reads data synchronously up to the specified number of bytes. - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? - /// Reads the available data synchronously up to the end of file or maximum - /// number of bytes. - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? - /// Moves the file pointer to the specified offset within the file. - func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws - /// Disallows further access to the represented file or communications channel - /// and signals end of file on communications channels that permit writing. - func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -} - -protocol PigeonApiProtocolFileHandle { -} - -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateFileHandle - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { - let codec: FlutterStandardMessageCodec = - api != nil - ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) - : FlutterStandardMessageCodec.sharedInstance() - let forReadingAtPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - forReadingAtPathChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pathArg = args[0] as! String - do { - let result = try api.pigeonDelegate.forReadingAtPath(pigeonApi: api, path: pathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - forReadingAtPathChannel.setMessageHandler(nil) - } - let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readUpToCountChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - let countArg = args[1] as! Int64 - do { - let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - readUpToCountChannel.setMessageHandler(nil) - } - let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readToEndChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - do { - let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - readToEndChannel.setMessageHandler(nil) - } - let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - seekChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - let offsetArg = args[1] as! Int64 - do { - try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - seekChannel.setMessageHandler(nil) - } - let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - closeChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - do { - try api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - closeChannel.setMessageHandler(nil) - } - } - - ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 78dd2cd3cff9..3843f9385e22 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.5), do not edit directly. +// Autogenerated from Pigeon (v26.1.7), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -59,9 +59,7 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError( - code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", - details: "") + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -116,12 +114,12 @@ func deepEqualsCrossFileDarwinApis(_ lhs: Any?, _ rhs: Any?) -> Bool { func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { if let valueList = value as? [AnyHashable] { - for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } - return + for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } + return } if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { + for key in valueDict.keys { hasher.combine(key) deepHashCrossFileDarwinApis(value: valueDict[key]!, hasher: &hasher) } @@ -135,12 +133,14 @@ func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { return hasher.combine(String(describing: value)) } + /// Handles the callback when an object is deallocated. protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. func onDeinit(identifier: Int64) } + // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -156,18 +156,14 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, - delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( - identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = - objc_getAssociatedObject(instance, associatedObjectKey) - as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -179,6 +175,7 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } + /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -282,8 +279,7 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach( - to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -364,6 +360,7 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } + private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -376,15 +373,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, - instanceManager: CrossFileDarwinApisPigeonInstanceManager? - ) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", - binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -399,9 +390,7 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", - binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -417,13 +406,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference( - identifier identifierArg: Int64, completion: @escaping (Result) -> Void - ) { - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -443,8 +428,7 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) - -> PigeonApiFileHandle + func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -457,15 +441,12 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: - CrossFileDarwinApisPigeonInternalFinalizerDelegate - { + private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -479,9 +460,7 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init( - binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - ) { + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -490,25 +469,18 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiFileHandle.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: - FlutterStandardReaderWriter -{ +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: - CrossFileDarwinApisPigeonCodecReader - { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -532,9 +504,7 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: - CrossFileDarwinApisPigeonCodecWriter - { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -543,26 +513,24 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] - || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String - { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { super.writeValue(value) return } + if let instance = value as? FileHandle { pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) return } - if let instance = value as AnyObject?, - pigeonRegistrar.instanceManager.containsInstance(instance) + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -580,13 +548,11 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( - data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( - data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) } } @@ -599,6 +565,7 @@ struct FileExistsResult: Hashable { /// Whether th var isDirectory: Bool + // swift-format-ignore: AlwaysUseLowerCamelCase static func fromList(_ pigeonVar_list: [Any?]) -> FileExistsResult? { let exists = pigeonVar_list[0] as! Bool @@ -616,8 +583,7 @@ struct FileExistsResult: Hashable { ] } static func == (lhs: FileExistsResult, rhs: FileExistsResult) -> Bool { - return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) - } + return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) } func hash(into hasher: inout Hasher) { deepHashCrossFileDarwinApis(value: toList(), hasher: &hasher) } @@ -656,10 +622,11 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec( - readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } +/// Api for getting access to file information. +/// /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference @@ -669,30 +636,30 @@ protocol CrossFileDarwinApi { func isReadableFile(url: String) throws -> Bool /// Whether a file or directory exists at a specified path. func fileExists(url: String) throws -> FileExistsResult - /// The file’s last modified date. + /// The file’s last modified date in milliseconds since epoch. func fileModificationDate(url: String) throws -> Int64? /// The file’s size in bytes. func fileSize(url: String) throws -> Int64? /// Performs a shallow search of the specified directory and returns the paths /// of any contained items. func list(url: String) throws -> [String] + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + func startAccessingSecurityScopedResource(url: String) throws -> Bool + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + func stopAccessingSecurityScopedResource(url: String) throws } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp( - binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, - messageChannelSuffix: String = "" - ) { + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -708,10 +675,7 @@ class CrossFileDarwinApiSetup { tryCreateBookmarkedUrlChannel.setMessageHandler(nil) } /// Whether the invoking object appears able to read a specified file. - let isReadableFileChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -727,9 +691,7 @@ class CrossFileDarwinApiSetup { isReadableFileChannel.setMessageHandler(nil) } /// Whether a file or directory exists at a specified path. - let fileExistsChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileExistsChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -744,11 +706,8 @@ class CrossFileDarwinApiSetup { } else { fileExistsChannel.setMessageHandler(nil) } - /// The file’s last modified date. - let fileModificationDateChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + /// The file’s last modified date in milliseconds since epoch. + let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileModificationDateChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -764,9 +723,7 @@ class CrossFileDarwinApiSetup { fileModificationDateChannel.setMessageHandler(nil) } /// The file’s size in bytes. - let fileSizeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { fileSizeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -783,9 +740,7 @@ class CrossFileDarwinApiSetup { } /// Performs a shallow search of the specified directory and returns the paths /// of any contained items. - let listChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { listChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -800,6 +755,40 @@ class CrossFileDarwinApiSetup { } else { listChannel.setMessageHandler(nil) } + /// In an app that has adopted App Sandbox, makes the resource pointed to by a + /// security-scoped URL available to the app. + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.startAccessingSecurityScopedResource(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + } + /// In an app that adopts App Sandbox, revokes access to the resource pointed + /// to by a security-scoped URL. + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + try api.stopAccessingSecurityScopedResource(url: urlArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + } } } protocol PigeonApiDelegateFileHandle { @@ -807,12 +796,10 @@ protocol PigeonApiDelegateFileHandle { /// socket at the specified path. func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? /// Reads data synchronously up to the specified number of bytes. - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) - throws -> FlutterStandardTypedData? + func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? /// Reads the available data synchronously up to the end of file or maximum /// number of bytes. - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws - -> FlutterStandardTypedData? + func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? /// Moves the file pointer to the specified offset within the file. func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws /// Disallows further access to the represented file or communications channel @@ -823,28 +810,20 @@ protocol PigeonApiDelegateFileHandle { protocol PigeonApiProtocolFileHandle { } -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { +final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateFileHandle - init( - pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, - delegate: PigeonApiDelegateFileHandle - ) { + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle? - ) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let forReadingAtPathChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath", - binaryMessenger: binaryMessenger, codec: codec) + let forReadingAtPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath", binaryMessenger: binaryMessenger, codec: codec) if let api = api { forReadingAtPathChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -859,17 +838,14 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { forReadingAtPathChannel.setMessageHandler(nil) } - let readUpToCountChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", - binaryMessenger: binaryMessenger, codec: codec) + let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) if let api = api { readUpToCountChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let countArg = args[1] as! Int64 do { - let result = try api.pigeonDelegate.readUpToCount( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) + let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -878,16 +854,13 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { readUpToCountChannel.setMessageHandler(nil) } - let readToEndChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", - binaryMessenger: binaryMessenger, codec: codec) + let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) if let api = api { readToEndChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle do { - let result = try api.pigeonDelegate.readToEnd( - pigeonApi: api, pigeonInstance: pigeonInstanceArg) + let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -896,17 +869,14 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { readToEndChannel.setMessageHandler(nil) } - let seekChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", - binaryMessenger: binaryMessenger, codec: codec) + let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) if let api = api { seekChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! FileHandle let offsetArg = args[1] as! Int64 do { - try api.pigeonDelegate.seek( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) + try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -915,9 +885,7 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } else { seekChannel.setMessageHandler(nil) } - let closeChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", - binaryMessenger: binaryMessenger, codec: codec) + let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) if let api = api { closeChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -935,25 +903,21 @@ final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { } ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: FileHandle, completion: @escaping (Result) -> Void - ) { + func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( - pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index a0738011f7eb..a334731ee450 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -9,7 +9,8 @@ import 'package:pigeon/pigeon.dart'; @ConfigurePigeon( PigeonOptions( dartOut: 'lib/src/cross_file_darwin_apis.g.dart', - swiftOut: 'darwin/Classes/CrossFileDarwinApis.g.swift', + swiftOut: + 'darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift', copyrightHeader: 'pigeons/copyright.txt', ), ) From 303c0c535f6884c8651c634f0b30214a89a8468d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:35:41 -0500 Subject: [PATCH 151/398] also sho length --- packages/cross_file/cross_file_darwin/example/lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 4cb5359abbd0..43b332515d93 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -57,6 +57,7 @@ class FileOpenScreen extends StatelessWidget { case final XFile file: final String filename = await file.name() ?? file.uri; debugPrint('\tFile: $filename'); + debugPrint('\t\tFile Length: ${await file.length()}'); case final XDirectory directory: debugPrint('\tDirectory: ${directory.uri}'); } From 7e48889769cdb9ac8b702e025a266b8ba55d5b9c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 10 Feb 2026 19:58:57 -0500 Subject: [PATCH 152/398] keep bookmarking uris --- .../CrossFileDarwinApis.g.swift | 773 ----------------- .../CrossFileDarwinPlugin.swift | 13 - .../cross_file_darwin/ProxyAPIRegistrar.swift | 36 - .../CrossFileDarwinApiImpl.swift | 44 +- .../FileHandleProxyAPIDelegate.swift | 66 -- .../lib/cross_file_darwin.dart | 4 - .../lib/src/cross_file_darwin.dart | 16 - .../lib/src/cross_file_darwin_apis.g.dart | 815 +----------------- .../lib/src/darwin_cross_directory.dart | 5 + .../lib/src/darwin_cross_file.dart | 5 + ...darwin_scoped_storage_cross_directory.dart | 89 -- .../src/darwin_scoped_storage_cross_file.dart | 171 ---- .../lib/src/security_scoped_resource.dart | 7 + .../pigeons/cross_file_darwin_apis.dart | 50 -- 14 files changed, 22 insertions(+), 2072 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/FileHandleProxyAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart delete mode 100644 packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 3843f9385e22..a3d3a6406986 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -58,10 +58,6 @@ private func wrapError(_ error: Any) -> [Any?] { ] } -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") -} - private func isNullish(_ value: Any?) -> Bool { return value is NSNull || value == nil } @@ -71,544 +67,11 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } -func deepEqualsCrossFileDarwinApis(_ lhs: Any?, _ rhs: Any?) -> Bool { - let cleanLhs = nilOrValue(lhs) as Any? - let cleanRhs = nilOrValue(rhs) as Any? - switch (cleanLhs, cleanRhs) { - case (nil, nil): - return true - - case (nil, _), (_, nil): - return false - - case is (Void, Void): - return true - - case let (cleanLhsHashable, cleanRhsHashable) as (AnyHashable, AnyHashable): - return cleanLhsHashable == cleanRhsHashable - - case let (cleanLhsArray, cleanRhsArray) as ([Any?], [Any?]): - guard cleanLhsArray.count == cleanRhsArray.count else { return false } - for (index, element) in cleanLhsArray.enumerated() { - if !deepEqualsCrossFileDarwinApis(element, cleanRhsArray[index]) { - return false - } - } - return true - - case let (cleanLhsDictionary, cleanRhsDictionary) as ([AnyHashable: Any?], [AnyHashable: Any?]): - guard cleanLhsDictionary.count == cleanRhsDictionary.count else { return false } - for (key, cleanLhsValue) in cleanLhsDictionary { - guard cleanRhsDictionary.index(forKey: key) != nil else { return false } - if !deepEqualsCrossFileDarwinApis(cleanLhsValue, cleanRhsDictionary[key]!) { - return false - } - } - return true - - default: - // Any other type shouldn't be able to be used with pigeon. File an issue if you find this to be untrue. - return false - } -} - -func deepHashCrossFileDarwinApis(value: Any?, hasher: inout Hasher) { - if let valueList = value as? [AnyHashable] { - for item in valueList { deepHashCrossFileDarwinApis(value: item, hasher: &hasher) } - return - } - - if let valueDict = value as? [AnyHashable: AnyHashable] { - for key in valueDict.keys { - hasher.combine(key) - deepHashCrossFileDarwinApis(value: valueDict[key]!, hasher: &hasher) - } - return - } - - if let hashableValue = value as? AnyHashable { - hasher.combine(hashableValue.hashValue) - } - - return hasher.combine(String(describing: value)) -} - - -/// Handles the callback when an object is deallocated. -protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { - /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. - func onDeinit(identifier: Int64) -} - - -// Attaches to an object to receive a callback when the object is deallocated. -internal final class CrossFileDarwinApisPigeonInternalFinalizer { - internal static let associatedObjectKey = malloc(1)! - - private let identifier: Int64 - // Reference to the delegate is weak because the callback should be ignored if the - // `InstanceManager` is deallocated. - internal weak var delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate? - - private init(identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { - self.identifier = identifier - self.delegate = delegate - } - - internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate - ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) - objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) - } - - static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer - if let finalizer = finalizer { - finalizer.delegate = nil - objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) - } - } - - deinit { - delegate?.onDeinit(identifier: identifier) - } -} - - -/// Maintains instances used to communicate with the corresponding objects in Dart. -/// -/// Objects stored in this container are represented by an object in Dart that is also stored in -/// an InstanceManager with the same identifier. -/// -/// When an instance is added with an identifier, either can be used to retrieve the other. -/// -/// Added instances are added as a weak reference and a strong reference. When the strong -/// reference is removed and the weak reference is deallocated,`CrossFileDarwinApisPigeonInternalFinalizerDelegate.onDeinit` -/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is -/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), -/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually -/// again. -/// -/// Accessing and inserting to an InstanceManager is thread safe. -final class CrossFileDarwinApisPigeonInstanceManager { - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously from Dart. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - private static let minHostCreatedIdentifier: Int64 = 65536 - - private let lockQueue = DispatchQueue(label: "CrossFileDarwinApisPigeonInstanceManager") - private let identifiers: NSMapTable = NSMapTable( - keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) - private let weakInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) - private let strongInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) - private let finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate - private var nextIdentifier: Int64 = minHostCreatedIdentifier - - public init(finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { - self.finalizerDelegate = finalizerDelegate - } - - /// Adds a new instance that was instantiated from Dart. - /// - /// The same instance can be added multiple times, but each identifier must be unique. This allows - /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. - /// - /// - Parameters: - /// - instance: the instance to be stored - /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique - func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - lockQueue.async { - self.addInstance(instance, withIdentifier: identifier) - } - } - - /// Adds a new instance that was instantiated from the host platform. - /// - /// - Parameters: - /// - instance: the instance to be stored. This must be unique to all other added instances. - /// - Returns: the unique identifier (>= 0) stored with instance - func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { - assert(!containsInstance(instance), "Instance of \(instance) has already been added.") - var identifier: Int64 = -1 - lockQueue.sync { - identifier = nextIdentifier - nextIdentifier += 1 - self.addInstance(instance, withIdentifier: identifier) - } - return identifier - } - - /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier paired to an instance. - /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if - /// the manager doesn't contain the value - func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) - strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - /// Retrieves the instance associated with identifier. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier associated with an instance - /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func instance(forIdentifier instanceIdentifier: Int64) -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - assert(identifier >= 0) - assert( - weakInstances.object(forKey: identifier as NSNumber) == nil, - "Identifier has already been added: \(identifier)") - identifiers.setObject(NSNumber(value: identifier), forKey: instance) - weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) - strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) - } - - /// Retrieves the identifier paired with an instance. - /// - /// If the manager contains a strong reference to `instance`, it will return the identifier - /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new - /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. - /// - /// If this method returns a nonnull identifier, this method also expects the Dart - /// `CrossFileDarwinApisPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - /// identifier is associated with. - /// - /// - Parameters: - /// - instance: an instance that may be stored in the manager - /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { - var identifier: Int64? = nil - lockQueue.sync { - if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { - strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) - identifier = existingIdentifier - } - } - return identifier - } - - /// Whether this manager contains the given `instance`. - /// - /// - Parameters: - /// - instance: the instance whose presence in this manager is to be tested - /// - Returns: whether this manager contains the given `instance` - func containsInstance(_ instance: AnyObject) -> Bool { - var containsInstance = false - lockQueue.sync { - containsInstance = identifiers.object(forKey: instance) != nil - } - return containsInstance - } - - /// Removes all of the instances from this manager. - /// - /// The manager will be empty after this call returns. - func removeAllObjects() throws { - lockQueue.sync { - let weakInstancesEnumerator = weakInstances.objectEnumerator()! - while let instance = weakInstancesEnumerator.nextObject() { - CrossFileDarwinApisPigeonInternalFinalizer.detach(from: instance as AnyObject) - } - identifiers.removeAllObjects() - weakInstances.removeAllObjects() - strongInstances.removeAllObjects() - nextIdentifier = CrossFileDarwinApisPigeonInstanceManager.minHostCreatedIdentifier - } - } - - /// The number of instances stored as a strong reference. - /// - /// For debugging and testing purposes. - internal var strongInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = strongInstances.count - } - return count - } - - /// The number of instances stored as a weak reference. - /// - /// For debugging and testing purposes. NSMapTables that store keys or objects as weak - /// reference will be reclaimed non-deterministically. - internal var weakInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = weakInstances.count - } - return count - } -} - - -private class CrossFileDarwinApisPigeonInstanceManagerApi { - /// The codec used for serializing messages. - var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } - - /// Handles sending and receiving messages with Dart. - unowned let binaryMessenger: FlutterBinaryMessenger - - init(binaryMessenger: FlutterBinaryMessenger) { - self.binaryMessenger = binaryMessenger - } - - /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { - let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - removeStrongReferenceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! Int64 - do { - let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - removeStrongReferenceChannel.setMessageHandler(nil) - } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - clearChannel.setMessageHandler { _, reply in - do { - try instanceManager.removeAllObjects() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - clearChannel.setMessageHandler(nil) - } - } - - /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([identifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } -} -protocol CrossFileDarwinApisPigeonProxyApiDelegate { - /// An implementation of [PigeonApiFileHandle] used to add a new Dart instance of - /// `FileHandle` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiFileHandle -} - -open class CrossFileDarwinApisPigeonProxyApiRegistrar { - let binaryMessenger: FlutterBinaryMessenger - let apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - let instanceManager: CrossFileDarwinApisPigeonInstanceManager - /// Whether APIs should ignore calling to Dart. - public var ignoreCallsToDart = false - private var _codec: FlutterStandardMessageCodec? - var codec: FlutterStandardMessageCodec { - if _codec == nil { - _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) - } - return _codec! - } - - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { - let api: CrossFileDarwinApisPigeonInstanceManagerApi - - init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { - self.api = api - } - - public func onDeinit(identifier: Int64) { - api.removeStrongReference(identifier: identifier) { - _ in - } - } - } - - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { - self.binaryMessenger = binaryMessenger - self.apiDelegate = apiDelegate - self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( - finalizerDelegate: InstanceManagerApiFinalizerDelegate( - CrossFileDarwinApisPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) - } - - func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiFileHandle(self)) - } - func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) - PigeonApiFileHandle.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - } -} -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 128: - let identifier = self.readValue() - let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( - forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) - if instance == nil { - print("Failed to find instance with identifier: \(identifier!)") - } - return instance - default: - return super.readValue(ofType: type) - } - } - } - - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { - super.writeValue(value) - return - } - - - if let instance = value as? FileHandle { - pigeonRegistrar.apiDelegate.pigeonApiFileHandle(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) - return - } - - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) - { - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) - } else { - print("Unsupported value: \(value) of \(type(of: value))") - assert(false, "Unsupported value for CrossFileDarwinApisPigeonInternalProxyApiCodecWriter") - } - - } - } - - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - } - - override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) - } -} - -/// Result of a call to `CrossFileDarwinApi.fileExists`. -/// -/// Generated class from Pigeon that represents data sent in messages. -struct FileExistsResult: Hashable { - /// Whether the file exists. - var exists: Bool - /// Whether th - var isDirectory: Bool - - - // swift-format-ignore: AlwaysUseLowerCamelCase - static func fromList(_ pigeonVar_list: [Any?]) -> FileExistsResult? { - let exists = pigeonVar_list[0] as! Bool - let isDirectory = pigeonVar_list[1] as! Bool - - return FileExistsResult( - exists: exists, - isDirectory: isDirectory - ) - } - func toList() -> [Any?] { - return [ - exists, - isDirectory, - ] - } - static func == (lhs: FileExistsResult, rhs: FileExistsResult) -> Bool { - return deepEqualsCrossFileDarwinApis(lhs.toList(), rhs.toList()) } - func hash(into hasher: inout Hasher) { - deepHashCrossFileDarwinApis(value: toList(), hasher: &hasher) - } -} private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 129: - return FileExistsResult.fromList(self.readValue() as! [Any?]) - default: - return super.readValue(ofType: type) - } - } } private class CrossFileDarwinApisPigeonCodecWriter: FlutterStandardWriter { - override func writeValue(_ value: Any) { - if let value = value as? FileExistsResult { - super.writeByte(129) - super.writeValue(value.toList()) - } else { - super.writeValue(value) - } - } } private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderWriter { @@ -632,17 +95,6 @@ protocol CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. func tryCreateBookmarkedUrl(url: String) throws -> String? - /// Whether the invoking object appears able to read a specified file. - func isReadableFile(url: String) throws -> Bool - /// Whether a file or directory exists at a specified path. - func fileExists(url: String) throws -> FileExistsResult - /// The file’s last modified date in milliseconds since epoch. - func fileModificationDate(url: String) throws -> Int64? - /// The file’s size in bytes. - func fileSize(url: String) throws -> Int64? - /// Performs a shallow search of the specified directory and returns the paths - /// of any contained items. - func list(url: String) throws -> [String] /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. func startAccessingSecurityScopedResource(url: String) throws -> Bool @@ -674,87 +126,6 @@ class CrossFileDarwinApiSetup { } else { tryCreateBookmarkedUrlChannel.setMessageHandler(nil) } - /// Whether the invoking object appears able to read a specified file. - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - isReadableFileChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.isReadableFile(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - isReadableFileChannel.setMessageHandler(nil) - } - /// Whether a file or directory exists at a specified path. - let fileExistsChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileExistsChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileExists(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileExistsChannel.setMessageHandler(nil) - } - /// The file’s last modified date in milliseconds since epoch. - let fileModificationDateChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileModificationDateChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileModificationDate(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileModificationDateChannel.setMessageHandler(nil) - } - /// The file’s size in bytes. - let fileSizeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - fileSizeChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.fileSize(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - fileSizeChannel.setMessageHandler(nil) - } - /// Performs a shallow search of the specified directory and returns the paths - /// of any contained items. - let listChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - listChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.list(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - listChannel.setMessageHandler(nil) - } /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) @@ -791,147 +162,3 @@ class CrossFileDarwinApiSetup { } } } -protocol PigeonApiDelegateFileHandle { - /// Returns a file handle initialized for reading the file, device, or named - /// socket at the specified path. - func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? - /// Reads data synchronously up to the specified number of bytes. - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) throws -> FlutterStandardTypedData? - /// Reads the available data synchronously up to the end of file or maximum - /// number of bytes. - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -> FlutterStandardTypedData? - /// Moves the file pointer to the specified offset within the file. - func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws - /// Disallows further access to the represented file or communications channel - /// and signals end of file on communications channels that permit writing. - func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws -} - -protocol PigeonApiProtocolFileHandle { -} - -final class PigeonApiFileHandle: PigeonApiProtocolFileHandle { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateFileHandle - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateFileHandle) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiFileHandle?) { - let codec: FlutterStandardMessageCodec = - api != nil - ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) - : FlutterStandardMessageCodec.sharedInstance() - let forReadingAtPathChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - forReadingAtPathChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pathArg = args[0] as! String - do { - let result = try api.pigeonDelegate.forReadingAtPath(pigeonApi: api, path: pathArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - forReadingAtPathChannel.setMessageHandler(nil) - } - let readUpToCountChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readUpToCountChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - let countArg = args[1] as! Int64 - do { - let result = try api.pigeonDelegate.readUpToCount(pigeonApi: api, pigeonInstance: pigeonInstanceArg, count: countArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - readUpToCountChannel.setMessageHandler(nil) - } - let readToEndChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readToEndChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - do { - let result = try api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - readToEndChannel.setMessageHandler(nil) - } - let seekChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.seek", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - seekChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - let offsetArg = args[1] as! Int64 - do { - try api.pigeonDelegate.seek(pigeonApi: api, pigeonInstance: pigeonInstanceArg, offset: offsetArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - seekChannel.setMessageHandler(nil) - } - let closeChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.FileHandle.close", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - closeChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! FileHandle - do { - try api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: pigeonInstanceArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - closeChannel.setMessageHandler(nil) - } - } - - ///Creates a Dart instance of FileHandle and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: FileHandle, completion: @escaping (Result) -> Void) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift index ee34131694ec..e5c30ac14440 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift @@ -11,14 +11,6 @@ #endif public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { - var proxyApiRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar? - - init(binaryMessenger: FlutterBinaryMessenger) { - proxyApiRegistrar = ProxyAPIRegistrar( - binaryMessenger: binaryMessenger) - proxyApiRegistrar?.setUp() - } - public static func register(with registrar: FlutterPluginRegistrar) { #if os(iOS) let messenger = registrar.messenger() @@ -27,8 +19,6 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { #endif CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: CrossFileDarwinApiImpl()) - let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger) - registrar.publish(plugin) } public func detachFromEngine(for registrar: FlutterPluginRegistrar) { @@ -39,8 +29,5 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { #endif CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: nil) - proxyApiRegistrar!.ignoreCallsToDart = true - proxyApiRegistrar!.tearDown() - proxyApiRegistrar = nil } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift deleted file mode 100644 index 09d515badab7..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#if os(iOS) -import Flutter -#elseif os(macOS) -import FlutterMacOS -#else -#error("Unsupported platform.") -#endif - -import Foundation - -/// Implementation of `CrossFileDarwinApisPigeonProxyApiRegistrar` that provides any additional resources needed by API implementations. -open class ProxyAPIRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar { - init(binaryMessenger: FlutterBinaryMessenger) { - super.init(binaryMessenger: binaryMessenger, apiDelegate: ProxyAPIDelegate()) - } - - func createConstructorNullError(type: Any.Type, parameters: [String: Any?]) -> PigeonError { - return PigeonError( - code: "ConstructorReturnedNullError", - message: "Failed to instantiate `\(String(describing: type))` with parameters: \(parameters)", - details: nil) - } -} - -/// Implementation of `WebKitLibraryPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation. -open class ProxyAPIDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { - func pigeonApiFileHandle(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) - -> PigeonApiFileHandle - { - return PigeonApiFileHandle(pigeonRegistrar: registrar, delegate: FileHandleProxyAPIDelegate()) - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index cf0c38fd75e2..62284cbb3b70 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -42,47 +42,11 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { return nil } - func isReadableFile(url: String) throws -> Bool { - return fileManager.isReadableFile(atPath: url) + func startAccessingSecurityScopedResource(url: String) throws -> Bool { + return URL(fileURLWithPath: url).startAccessingSecurityScopedResource() } - func fileExists(url: String) throws -> FileExistsResult { - var isDirectory: ObjCBool = true - let exists = fileManager.fileExists(atPath: url, isDirectory: &isDirectory) - return FileExistsResult(exists: exists, isDirectory: isDirectory.boolValue) + func stopAccessingSecurityScopedResource(url: String) throws { + URL(fileURLWithPath: url).stopAccessingSecurityScopedResource() } - - func fileIsDirectory(url: String) throws -> Bool { - var isDirectory: ObjCBool = true - return fileManager.fileExists(atPath: url, isDirectory: &isDirectory) - && isDirectory.boolValue - } - - func fileModificationDate(url: String) throws -> Int64? { - let attributes: NSDictionary = - try fileManager.attributesOfItem(atPath: url) as NSDictionary - if let date = attributes.fileModificationDate() { - return Int64(date.timeIntervalSince1970 * 1000) - } - - return nil - } - - func fileSize(url: String) throws -> Int64? { - let attributes: NSDictionary = - try fileManager.attributesOfItem(atPath: url) as NSDictionary - return Int64(attributes.fileSize()) - } - - func list(url: String) throws -> [String] { - return try fileManager.contentsOfDirectory(atPath: url) - } - - func startAccessingSecurityScopedResource(url: String) throws -> Bool { - return URL(fileURLWithPath: url).startAccessingSecurityScopedResource() - } - - func stopAccessingSecurityScopedResource(url: String) throws { - URL(fileURLWithPath: url).stopAccessingSecurityScopedResource() - } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/FileHandleProxyAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/FileHandleProxyAPIDelegate.swift deleted file mode 100644 index 67c030a9223b..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/FileHandleProxyAPIDelegate.swift +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#if os(iOS) -import Flutter -#elseif os(macOS) -import FlutterMacOS -#else -#error("Unsupported platform.") -#endif - -import Foundation - -/// ProxyApi implementation for `FileHandle`. -/// -/// This class may handle instantiating native object instances that are attached to a Dart instance -/// or handle method calls on the associated native class or an instance of that class. -class FileHandleProxyAPIDelegate: PigeonApiDelegateFileHandle { - func forReadingAtPath(pigeonApi: PigeonApiFileHandle, path: String) throws -> FileHandle? { - return FileHandle(forReadingAtPath: path) - } - - func readUpToCount(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, count: Int64) - throws -> FlutterStandardTypedData? - { - var data: Data? - if #available(iOS 13.4, macOS 10.15.4, *) { - data = try pigeonInstance.read(upToCount: Int(count)) - } else { - data = pigeonInstance.readData(ofLength: Int(count)) - } - - if let data = data { - return FlutterStandardTypedData(bytes: data) - } - - return nil - } - - func readToEnd(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws - -> FlutterStandardTypedData? - { - var bytes: Data? - if #available(iOS 13.4, macOS 10.15.4, *) { - bytes = try pigeonInstance.readToEnd() - } else { - bytes = pigeonInstance.readDataToEndOfFile() - } - - if let bytes = bytes { - return FlutterStandardTypedData(bytes: bytes) - } - - return nil - } - - func seek(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle, offset: Int64) throws { - let convertedOffset = UInt64(exactly: offset)! - try pigeonInstance.seek(toOffset: convertedOffset) - } - - func close(pigeonApi: PigeonApiFileHandle, pigeonInstance: FileHandle) throws { - try pigeonInstance.close() - } -} diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 5a2961bfce29..7cc5a8df2530 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -8,7 +8,3 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart export 'src/cross_file_darwin.dart'; export 'src/darwin_cross_directory.dart' show DarwinXDirectoryExtension; export 'src/darwin_cross_file.dart' show DarwinXFileExtension; -export 'src/darwin_scoped_storage_cross_directory.dart' - show DarwinScopedStorageXDirectoryExtension; -export 'src/darwin_scoped_storage_cross_file.dart' - show DarwinScopedStorageXFileExtension; diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index 47c06b0b6807..eeda1ff9016d 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -7,8 +7,6 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'darwin_cross_directory.dart'; import 'darwin_cross_file.dart'; -import 'darwin_scoped_storage_cross_directory.dart'; -import 'darwin_scoped_storage_cross_file.dart'; /// Implementation of [CrossFilePlatform] for iOS and macOS. base class CrossFileDarwin extends CrossFileIO { @@ -28,18 +26,4 @@ base class CrossFileDarwin extends CrossFileIO { ) { return DarwinXDirectory(params); } - - @override - DarwinScopedStorageXFile createPlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams params, - ) { - return DarwinScopedStorageXFile(params); - } - - @override - DarwinScopedStorageXDirectory createPlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams params, - ) { - return DarwinScopedStorageXDirectory(params); - } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 56424ffef5bf..f6190d27017a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -6,12 +6,10 @@ // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers import 'dart:async'; -import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; PlatformException _createConnectionError(String channelName) { return PlatformException( @@ -20,457 +18,6 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; - } - return [error.code, error.message, error.details]; -} -bool _deepEquals(Object? a, Object? b) { - if (a is List && b is List) { - return a.length == b.length && - a.indexed - .every(((int, dynamic) item) => _deepEquals(item.$2, b[item.$1])); - } - if (a is Map && b is Map) { - return a.length == b.length && a.entries.every((MapEntry entry) => - (b as Map).containsKey(entry.key) && - _deepEquals(entry.value, b[entry.key])); - } - return a == b; -} - -/// Provides overrides for the constructors and static members of each -/// Dart proxy class. -/// -/// This is only intended to be used with unit tests to prevent errors from -/// making message calls in a unit test. -/// -/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. -@visibleForTesting -class PigeonOverrides { - /// Overrides [FileHandle.forReadingAtPath]. - static Future Function(String)? fileHandle_forReadingAtPath; - - /// Sets all overridden ProxyApi class members to null. - static void pigeon_reset() { - fileHandle_forReadingAtPath = null; - } -} - -/// An immutable object that serves as the base class for all Dart proxy classes -/// and can provide functional copies of itself. -/// -/// All implementers are expected to be [immutable] as defined by the annotation -/// and override [pigeon_copy] returning an instance of itself. -@immutable -abstract class PigeonInternalProxyApiBaseClass { - /// Construct a [PigeonInternalProxyApiBaseClass]. - PigeonInternalProxyApiBaseClass({ - this.pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; - - /// Sends and receives binary data across the Flutter platform barrier. - /// - /// If it is null, the default BinaryMessenger will be used, which routes to - /// the host platform. - @protected - final BinaryMessenger? pigeon_binaryMessenger; - - /// Maintains instances stored to communicate with native language objects. - final PigeonInstanceManager pigeon_instanceManager; - - /// Instantiates and returns a functionally identical object to oneself. - /// - /// Outside of tests, this method should only ever be called by - /// [PigeonInstanceManager]. - /// - /// Subclasses should always override their parent's implementation of this - /// method. - @protected - PigeonInternalProxyApiBaseClass pigeon_copy(); -} - -/// Maintains instances used to communicate with the native objects they -/// represent. -/// -/// Added instances are stored as weak references and their copies are stored -/// as strong references to maintain access to their variables and callback -/// methods. Both are stored with the same identifier. -/// -/// When a weak referenced instance becomes inaccessible, -/// [onWeakReferenceRemoved] is called with its associated identifier. -/// -/// If an instance is retrieved and has the possibility to be used, -/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference -/// is added as a weak reference with the same identifier. This prevents a -/// scenario where the weak referenced instance was released and then later -/// returned by the host platform. -class PigeonInstanceManager { - /// Constructs a [PigeonInstanceManager]. - PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { - this.onWeakReferenceRemoved = (int identifier) { - _weakInstances.remove(identifier); - onWeakReferenceRemoved(identifier); - }; - _finalizer = Finalizer(this.onWeakReferenceRemoved); - } - - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously by the host platform. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - static const int _maxDartCreatedIdentifier = 65536; - - /// The default [PigeonInstanceManager] used by Dart proxy classes. - /// - /// On creation, this manager makes a call to clear the native - /// InstanceManager. This is to prevent identifier conflicts after a host - /// restart. - static final PigeonInstanceManager instance = _initInstance(); - - // Expando is used because it doesn't prevent its keys from becoming - // inaccessible. This allows the manager to efficiently retrieve an identifier - // of an instance without holding a strong reference to that instance. - // - // It also doesn't use `==` to search for identifiers, which would lead to an - // infinite loop when comparing an object to its copy. (i.e. which was caused - // by calling instanceManager.getIdentifier() inside of `==` while this was a - // HashMap). - final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; - late final Finalizer _finalizer; - int _nextIdentifier = 0; - - /// Called when a weak referenced instance is removed by [removeWeakReference] - /// or becomes inaccessible. - late final void Function(int) onWeakReferenceRemoved; - - static PigeonInstanceManager _initInstance() { - if (Platform.environment['FLUTTER_TEST'] == 'true') { - return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); - } - WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); - // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. - api.clear(); - final PigeonInstanceManager instanceManager = PigeonInstanceManager( - onWeakReferenceRemoved: (int identifier) { - api.removeStrongReference(identifier); - }, - ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - FileHandle.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - return instanceManager; - } - - /// Adds a new instance that was instantiated by Dart. - /// - /// In other words, Dart wants to add a new instance that will represent - /// an object that will be instantiated on the host platform. - /// - /// Throws assertion error if the instance has already been added. - /// - /// Returns the randomly generated id of the [instance] added. - int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { - assert(getIdentifier(instance) == null); - - final int identifier = _nextUniqueIdentifier(); - _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); - _finalizer.attach(instance, identifier, detach: instance); - - final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); - _identifiers[copy] = identifier; - _strongInstances[identifier] = copy; - return identifier; - } - - /// Removes the instance, if present, and call [onWeakReferenceRemoved] with - /// its identifier. - /// - /// Returns the identifier associated with the removed instance. Otherwise, - /// `null` if the instance was not found in this manager. - /// - /// This does not remove the strong referenced instance associated with - /// [instance]. This can be done with [remove]. - int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { - final int? identifier = getIdentifier(instance); - if (identifier == null) { - return null; - } - - _identifiers[instance] = null; - _finalizer.detach(instance); - onWeakReferenceRemoved(identifier); - - return identifier; - } - - /// Removes [identifier] and its associated strongly referenced instance, if - /// present, from the manager. - /// - /// Returns the strong referenced instance associated with [identifier] before - /// it was removed. Returns `null` if [identifier] was not associated with - /// any strong reference. - /// - /// Throws an `AssertionError` if the weak referenced instance associated with - /// [identifier] is not removed first. This can be done with - /// [removeWeakReference]. - T? remove(int identifier) { - final T? instance = _weakInstances[identifier]?.target as T?; - assert( - instance == null, - 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', - ); - return _strongInstances.remove(identifier) as T?; - } - - /// Retrieves the instance associated with identifier. - /// - /// The value returned is chosen from the following order: - /// - /// 1. A weakly referenced instance associated with identifier. - /// 2. If the only instance associated with identifier is a strongly - /// referenced instance, a copy of the instance is added as a weak reference - /// with the same identifier. Returning the newly created copy. - /// 3. If no instance is associated with identifier, returns null. - /// - /// This method also expects the host `InstanceManager` to have a strong - /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; - - if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; - if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); - _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); - _finalizer.attach(copy, identifier, detach: copy); - return copy as T; - } - return strongInstance as T?; - } - - return weakInstance as T; - } - - /// Retrieves the identifier associated with instance. - int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { - return _identifiers[instance]; - } - - /// Adds a new instance that was instantiated by the host platform. - /// - /// In other words, the host platform wants to add a new instance that - /// represents an object on the host platform. Stored with [identifier]. - /// - /// Throws assertion error if the instance or its identifier has already been - /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { - assert(!containsIdentifier(identifier)); - assert(getIdentifier(instance) == null); - assert(identifier >= 0); - - _identifiers[instance] = identifier; - _strongInstances[identifier] = instance; - } - - /// Whether this manager contains the given [identifier]. - bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || - _strongInstances.containsKey(identifier); - } - - int _nextUniqueIdentifier() { - late int identifier; - do { - identifier = _nextIdentifier; - _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; - } while (containsIdentifier(identifier)); - return identifier; - } -} - -/// Generated API for managing the Dart and native `PigeonInstanceManager`s. -class _PigeonInternalInstanceManagerApi { - /// Constructor for [_PigeonInternalInstanceManagerApi]. - _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; - - final BinaryMessenger? pigeonVar_binaryMessenger; - - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - static void setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? binaryMessenger, - PigeonInstanceManager? instanceManager, - }) { - { - final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null.'); - final List args = (message as List?)!; - final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); - try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - Future removeStrongReference(int identifier) async { - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - /// Clear the native `PigeonInstanceManager`. - /// - /// This is typically called after a hot restart. - Future clear() async { - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } -} - -class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - - -/// Result of a call to `CrossFileDarwinApi.fileExists`. -class FileExistsResult { - FileExistsResult({ - required this.exists, - required this.isDirectory, - }); - - /// Whether the file exists. - bool exists; - - /// Whether th - bool isDirectory; - - List _toList() { - return [ - exists, - isDirectory, - ]; - } - - Object encode() { - return _toList(); } - - static FileExistsResult decode(Object result) { - result as List; - return FileExistsResult( - exists: result[0]! as bool, - isDirectory: result[1]! as bool, - ); - } - - @override - // ignore: avoid_equals_and_hash_code_on_mutable_classes - bool operator ==(Object other) { - if (other is! FileExistsResult || other.runtimeType != runtimeType) { - return false; - } - if (identical(this, other)) { - return true; - } - return _deepEquals(encode(), other.encode()); - } - - @override - // ignore: avoid_equals_and_hash_code_on_mutable_classes - int get hashCode => Object.hashAll(_toList()) -; -} - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -479,9 +26,6 @@ class _PigeonCodec extends StandardMessageCodec { if (value is int) { buffer.putUint8(4); buffer.putInt64(value); - } else if (value is FileExistsResult) { - buffer.putUint8(129); - writeValue(buffer, value.encode()); } else { super.writeValue(buffer, value); } @@ -490,8 +34,6 @@ class _PigeonCodec extends StandardMessageCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 129: - return FileExistsResult.decode(readValue(buffer)!); default: return super.readValueOfType(type, buffer); } @@ -536,137 +78,6 @@ class CrossFileDarwinApi { } } - /// Whether the invoking object appears able to read a specified file. - Future isReadableFile(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } - } - - /// Whether a file or directory exists at a specified path. - Future fileExists(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileExists$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as FileExistsResult?)!; - } - } - - /// The file’s last modified date in milliseconds since epoch. - Future fileModificationDate(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileModificationDate$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as int?); - } - } - - /// The file’s size in bytes. - Future fileSize(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.fileSize$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as int?); - } - } - - /// Performs a shallow search of the specified directory and returns the paths - /// of any contained items. - Future> list(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.list$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as List?)!.cast(); - } - } - /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. Future startAccessingSecurityScopedResource(String url) async { @@ -720,227 +131,3 @@ class CrossFileDarwinApi { } } } -/// An object-oriented wrapper for a file descriptor. -/// -/// See https://developer.apple.com/documentation/foundation/filehandle. -class FileHandle extends PigeonInternalProxyApiBaseClass { - /// Constructs [FileHandle] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - FileHandle.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); - - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecFileHandle = - _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - FileHandle Function()? pigeon_newInstance, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null.'); - final List args = (message as List?)!; - final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_darwin.FileHandle.pigeon_newInstance was null, expected non-null int.'); - try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); - } - }); - } - } - } - - /// Returns a file handle initialized for reading the file, device, or named - /// socket at the specified path. - static Future forReadingAtPath( - String path, { - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) async { - if (PigeonOverrides.fileHandle_forReadingAtPath != null) { - return PigeonOverrides.fileHandle_forReadingAtPath!(path); - } - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.forReadingAtPath'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([path]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as FileHandle?); - } - } - - /// Reads data synchronously up to the specified number of bytes. - Future readUpToCount(int count) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.readUpToCount'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, count]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as Uint8List?); - } - } - - /// Reads the available data synchronously up to the end of file or maximum - /// number of bytes. - Future readToEnd() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.readToEnd'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as Uint8List?); - } - } - - /// Moves the file pointer to the specified offset within the file. - Future seek(int offset) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.seek'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, offset]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - /// Disallows further access to the represented file or communications channel - /// and signals end of file on communications channels that permit writing. - Future close() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecFileHandle; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.FileHandle.close'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } - } - - @override - FileHandle pigeon_copy() { - return FileHandle.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ); - } -} - diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart index 133ae4c3ef7f..d4b93945f4f1 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart @@ -52,6 +52,11 @@ base class DarwinXDirectory extends IOXDirectory Future stopAccessingSecurityScopedResource() { return params.api.stopAccessingSecurityScopedResource(params.uri); } + + @override + Future toBookmarkedUri() async { + return params.api.tryCreateBookmarkedUrl(params.uri); + } } /// Provides platform specific features for [DarwinXDirectory]. diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart index d6027c29217e..5396a2b6b8ee 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart @@ -51,6 +51,11 @@ base class DarwinXFile extends IOXFile with DarwinXFileExtension { Future stopAccessingSecurityScopedResource() { return params.api.stopAccessingSecurityScopedResource(params.uri); } + + @override + Future toBookmarkedUri() async { + return params.api.tryCreateBookmarkedUrl(params.uri); + } } /// Provides platform specific features for [DarwinXFile]. diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart deleted file mode 100644 index e8674a0c32af..000000000000 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; - -import 'cross_file_darwin_apis.g.dart'; -import 'darwin_scoped_storage_cross_file.dart'; - -/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and -/// macOS. -@immutable -base class DarwinScopedStorageXDirectoryCreationParams - extends PlatformScopedStorageXDirectoryCreationParams { - /// Constructs a [PlatformScopedStorageXDirectoryCreationParams]. - DarwinScopedStorageXDirectoryCreationParams({ - required super.uri, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(); - - /// The API used to call to native code to interact with files. - @visibleForTesting - final CrossFileDarwinApi api; -} - -/// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. -base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory - with DarwinScopedStorageXDirectoryExtension { - /// Constructs an [DarwinScopedStorageXDirectory]. - DarwinScopedStorageXDirectory(super.params) : super.implementation(); - - @override - late final DarwinScopedStorageXDirectoryCreationParams params = - super.params is DarwinScopedStorageXDirectoryCreationParams - ? super.params as DarwinScopedStorageXDirectoryCreationParams - : DarwinScopedStorageXDirectoryCreationParams(uri: super.params.uri); - - @override - PlatformXFileEntityExtension? get extension => this; - - @override - Future toBookmarkedDirectory() async { - final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( - params.uri, - ); - - return bookmarkedUrl != null - ? DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: bookmarkedUrl), - ) - : null; - } - - @override - Future exists() async { - final FileExistsResult result = await params.api.fileExists(params.uri); - return result.exists && result.isDirectory; - } - - @override - Stream list(ListParams params) async* { - for (final String url in await this.params.api.list(this.params.uri)) { - final FileExistsResult existsResult = await this.params.api.fileExists( - url, - ); - if (existsResult.isDirectory) { - yield DarwinScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams(uri: url), - ); - } else { - yield DarwinScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: url), - ); - } - } - } -} - -/// Provides platform specific features for [DarwinScopedStorageXDirectory]. -mixin DarwinScopedStorageXDirectoryExtension - implements PlatformScopedStorageXDirectoryExtension { - /// Attempt to create a bookmarked directory that serves as a persistent - /// reference to the directory. - /// - /// Throws exception if the directory could not be bookmarked or null if the - /// bookmark is stale. - Future toBookmarkedDirectory(); -} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart deleted file mode 100644 index 52ae9852b81a..000000000000 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:math'; - -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; -import 'package:path/path.dart' as path; - -import 'cross_file_darwin_apis.g.dart'; - -/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and -/// macOS. -@immutable -base class DarwinScopedStorageXFileCreationParams - extends PlatformScopedStorageXFileCreationParams { - /// Constructs a [DarwinScopedStorageXFileCreationParams]. - DarwinScopedStorageXFileCreationParams({ - required super.uri, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(); - - /// The API used to call to native code to interact with files. - @visibleForTesting - final CrossFileDarwinApi api; -} - -/// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. -base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile - with DarwinScopedStorageXFileExtension { - /// Constructs a [DarwinScopedStorageXFile]. - DarwinScopedStorageXFile(super.params) : super.implementation(); - - /// Maximum number of bytes to read at a time from the native iOS - /// `FileHandle`. - /// - /// Only visible for testing. - @visibleForTesting - static const int maxByteArrayLen = 4 * 1024; - - @override - late final DarwinScopedStorageXFileCreationParams params = - super.params is DarwinScopedStorageXFileCreationParams - ? super.params as DarwinScopedStorageXFileCreationParams - : DarwinScopedStorageXFileCreationParams(uri: super.params.uri); - - @override - PlatformXFileEntityExtension? get extension => this; - - @override - Future toBookmarkedFile() async { - final String? bookmarkedUrl = await params.api.tryCreateBookmarkedUrl( - params.uri, - ); - - return bookmarkedUrl != null - ? DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: bookmarkedUrl), - ) - : null; - } - - @override - Future canRead() => params.api.isReadableFile(params.uri); - - @override - Future exists() async { - final FileExistsResult result = await params.api.fileExists(params.uri); - return result.exists && !result.isDirectory; - } - - @override - Future lastModified() async { - final int? lastModifiedSinceEpoch = await params.api.fileModificationDate( - params.uri, - ); - return lastModifiedSinceEpoch != null - ? DateTime.fromMillisecondsSinceEpoch(lastModifiedSinceEpoch) - : null; - } - - @override - Future length() => params.api.fileSize(params.uri); - - @override - Future name() async => path.basename(params.uri); - - @override - Stream openRead([int? start, int? end]) async* { - final int? fileLength = await length(); - if (fileLength == null) { - throw UnsupportedError( - 'Cannot access file length of file with uri: ${params.uri}.', - ); - } - - int bytesToRead = (end ?? fileLength) - (start ?? 0); - assert(bytesToRead >= 0); - - final FileHandle? handle = await FileHandle.forReadingAtPath(params.uri); - if (handle == null) { - throw UnsupportedError( - 'Cannot create native `FileHandle` with uri: ${params.uri}.', - ); - } - - try { - if (start != null && start > 0) { - await handle.seek(start); - } - - do { - final Uint8List? bytes = await handle.readUpToCount( - min(bytesToRead, maxByteArrayLen), - ); - - if (bytes == null) { - throw UnsupportedError( - 'Failed to read bytes from file: ${params.uri}', - ); - } else { - yield bytes; - } - - bytesToRead -= bytes.length; - } while (bytesToRead > 0); - } finally { - await handle.close(); - } - } - - @override - Future readAsBytes() async { - final FileHandle? handle = await FileHandle.forReadingAtPath(params.uri); - if (handle == null) { - throw UnsupportedError( - 'Cannot create native `FileHandle` with uri: ${params.uri}.', - ); - } - - try { - final Uint8List? bytes = await handle.readToEnd(); - if (bytes == null) { - throw UnsupportedError('Failed to read bytes from file: ${params.uri}'); - } - - return bytes; - } finally { - await handle.close(); - } - } - - @override - Future readAsString({Encoding encoding = utf8}) async { - return encoding.decodeStream(openRead()); - } -} - -/// Provides platform specific features for [DarwinScopedStorageXFile]. -mixin DarwinScopedStorageXFileExtension - implements PlatformScopedStorageXFileExtension { - /// Attempt to create a bookmarked file that serves as a persistent reference - /// to the file. - /// - /// Throws exception if the file could not be bookmarked or null if the - /// bookmark is stale. - Future toBookmarkedFile(); -} diff --git a/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart b/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart index 66b3aa632e83..c9bb5543665e 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart @@ -11,4 +11,11 @@ mixin SecurityScopedResource { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. Future stopAccessingSecurityScopedResource(); + + /// Attempt to create a bookmarked URI that serves as a persistent reference + /// to the resource. + /// + /// Throws exception if the file could not be bookmarked or null if the + /// bookmark is stale. + Future toBookmarkedUri(); } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index a334731ee450..1184477e8be3 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -14,15 +14,6 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) -/// Result of a call to `CrossFileDarwinApi.fileExists`. -class FileExistsResult { - /// Whether the file exists. - late bool exists; - - /// Whether th - late bool isDirectory; -} - /// Api for getting access to file information. @HostApi() abstract class CrossFileDarwinApi { @@ -30,22 +21,6 @@ abstract class CrossFileDarwinApi { /// to a file. String? tryCreateBookmarkedUrl(String url); - /// Whether the invoking object appears able to read a specified file. - bool isReadableFile(String url); - - /// Whether a file or directory exists at a specified path. - FileExistsResult fileExists(String url); - - /// The file’s last modified date in milliseconds since epoch. - int? fileModificationDate(String url); - - /// The file’s size in bytes. - int? fileSize(String url); - - /// Performs a shallow search of the specified directory and returns the paths - /// of any contained items. - List list(String url); - /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. bool startAccessingSecurityScopedResource(String url); @@ -54,28 +29,3 @@ abstract class CrossFileDarwinApi { /// to by a security-scoped URL. void stopAccessingSecurityScopedResource(String url); } - -/// An object-oriented wrapper for a file descriptor. -/// -/// See https://developer.apple.com/documentation/foundation/filehandle. -@ProxyApi() -abstract class FileHandle { - /// Returns a file handle initialized for reading the file, device, or named - /// socket at the specified path. - @static - FileHandle? forReadingAtPath(String path); - - /// Reads data synchronously up to the specified number of bytes. - Uint8List? readUpToCount(int count); - - /// Reads the available data synchronously up to the end of file or maximum - /// number of bytes. - Uint8List? readToEnd(); - - /// Moves the file pointer to the specified offset within the file. - void seek(int offset); - - /// Disallows further access to the represented file or communications channel - /// and signals end of file on communications channels that permit writing. - void close(); -} From b1f38e838358d91c126162cf8bdc3b263e28397a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 12:08:37 -0500 Subject: [PATCH 153/398] update unit tests --- .../lib/cross_file_darwin.dart | 1 + .../test/darwin_cross_directory_test.dart | 57 +++++ ...=> darwin_cross_directory_test.mocks.dart} | 50 +--- .../test/darwin_cross_file_test.dart | 52 ++++ .../test/darwin_cross_file_test.mocks.dart | 71 ++++++ ...n_scoped_storage_cross_directory_test.dart | 56 ----- ...darwin_scoped_storage_cross_file_test.dart | 229 ------------------ ..._scoped_storage_cross_file_test.mocks.dart | 182 -------------- 8 files changed, 189 insertions(+), 509 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart rename packages/cross_file/cross_file_darwin/test/{darwin_scoped_storage_cross_directory_test.mocks.dart => darwin_cross_directory_test.mocks.dart} (58%) create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.mocks.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 7cc5a8df2530..091dad830432 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -8,3 +8,4 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart export 'src/cross_file_darwin.dart'; export 'src/darwin_cross_directory.dart' show DarwinXDirectoryExtension; export 'src/darwin_cross_file.dart' show DarwinXFileExtension; +export 'src/security_scoped_resource.dart'; diff --git a/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart new file mode 100644 index 000000000000..2e36fe66c84c --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart @@ -0,0 +1,57 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; +import 'package:cross_file_darwin/src/darwin_cross_directory.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'darwin_cross_directory_test.mocks.dart'; + +@GenerateMocks([CrossFileDarwinApi]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + test('startAccessingSecurityScopedResource', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const result = true; + when( + mockApi.startAccessingSecurityScopedResource(uri), + ).thenAnswer((_) async => result); + + final file = DarwinXDirectory( + DarwinXDirectoryCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.startAccessingSecurityScopedResource(), result); + }); + + test('stopAccessingSecurityScopedResource', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + + final file = DarwinXDirectory( + DarwinXDirectoryCreationParams(uri: uri, api: mockApi), + ); + + await file.stopAccessingSecurityScopedResource(); + verify(mockApi.stopAccessingSecurityScopedResource(uri)); + }); + + test('tryCreateBookmarkedUrl', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const bookmarkedUri = 'newUri'; + when( + mockApi.tryCreateBookmarkedUrl(uri), + ).thenAnswer((_) async => bookmarkedUri); + + final file = DarwinXDirectory( + DarwinXDirectoryCreationParams(uri: uri, api: mockApi), + ); + + expect(await file.toBookmarkedUri(), bookmarkedUri); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.mocks.dart similarity index 58% rename from packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart rename to packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.mocks.dart index 23a7b78e74ad..6a4734085fbd 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.mocks.dart @@ -1,5 +1,5 @@ // Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart. +// in cross_file_darwin/test/darwin_cross_directory_test.dart. // Do not manually edit this file. // ignore_for_file: no_leading_underscores_for_library_prefixes @@ -24,12 +24,6 @@ import 'package:mockito/src/dummies.dart' as _i3; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member -class _FakeFileExistsResult_0 extends _i1.SmartFake - implements _i2.FileExistsResult { - _FakeFileExistsResult_0(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - /// A class which mocks [CrossFileDarwinApi]. /// /// See the documentation for Mockito's code generation for more information. @@ -59,47 +53,19 @@ class MockCrossFileDarwinApi extends _i1.Mock as _i4.Future); @override - _i4.Future isReadableFile(String? url) => + _i4.Future startAccessingSecurityScopedResource(String? url) => (super.noSuchMethod( - Invocation.method(#isReadableFile, [url]), + Invocation.method(#startAccessingSecurityScopedResource, [url]), returnValue: _i4.Future.value(false), ) as _i4.Future); @override - _i4.Future<_i2.FileExistsResult> fileExists(String? url) => - (super.noSuchMethod( - Invocation.method(#fileExists, [url]), - returnValue: _i4.Future<_i2.FileExistsResult>.value( - _FakeFileExistsResult_0( - this, - Invocation.method(#fileExists, [url]), - ), - ), - ) - as _i4.Future<_i2.FileExistsResult>); - - @override - _i4.Future fileModificationDate(String? url) => - (super.noSuchMethod( - Invocation.method(#fileModificationDate, [url]), - returnValue: _i4.Future.value(), - ) - as _i4.Future); - - @override - _i4.Future fileSize(String? url) => - (super.noSuchMethod( - Invocation.method(#fileSize, [url]), - returnValue: _i4.Future.value(), - ) - as _i4.Future); - - @override - _i4.Future> list(String? url) => + _i4.Future stopAccessingSecurityScopedResource(String? url) => (super.noSuchMethod( - Invocation.method(#list, [url]), - returnValue: _i4.Future>.value([]), + Invocation.method(#stopAccessingSecurityScopedResource, [url]), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), ) - as _i4.Future>); + as _i4.Future); } diff --git a/packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.dart new file mode 100644 index 000000000000..867da5b32da0 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.dart @@ -0,0 +1,52 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; +import 'package:cross_file_darwin/src/darwin_cross_file.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'darwin_cross_file_test.mocks.dart'; + +@GenerateMocks([CrossFileDarwinApi]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('startAccessingSecurityScopedResource', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const result = true; + when( + mockApi.startAccessingSecurityScopedResource(uri), + ).thenAnswer((_) async => result); + + final file = DarwinXFile(DarwinXFileCreationParams(uri: uri, api: mockApi)); + + expect(await file.startAccessingSecurityScopedResource(), result); + }); + + test('stopAccessingSecurityScopedResource', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + + final file = DarwinXFile(DarwinXFileCreationParams(uri: uri, api: mockApi)); + + await file.stopAccessingSecurityScopedResource(); + verify(mockApi.stopAccessingSecurityScopedResource(uri)); + }); + + test('tryCreateBookmarkedUrl', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const bookmarkedUri = 'newUri'; + when( + mockApi.tryCreateBookmarkedUrl(uri), + ).thenAnswer((_) async => bookmarkedUri); + + final file = DarwinXFile(DarwinXFileCreationParams(uri: uri, api: mockApi)); + + expect(await file.toBookmarkedUri(), bookmarkedUri); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.mocks.dart new file mode 100644 index 000000000000..af889f8183e8 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/darwin_cross_file_test.mocks.dart @@ -0,0 +1,71 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_darwin/test/darwin_cross_file_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i4; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; +import 'package:mockito/src/dummies.dart' as _i3; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +/// A class which mocks [CrossFileDarwinApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCrossFileDarwinApi extends _i1.Mock + implements _i2.CrossFileDarwinApi { + MockCrossFileDarwinApi() { + _i1.throwOnMissingStub(this); + } + + @override + String get pigeonVar_messageChannelSuffix => + (super.noSuchMethod( + Invocation.getter(#pigeonVar_messageChannelSuffix), + returnValue: _i3.dummyValue( + this, + Invocation.getter(#pigeonVar_messageChannelSuffix), + ), + ) + as String); + + @override + _i4.Future tryCreateBookmarkedUrl(String? url) => + (super.noSuchMethod( + Invocation.method(#tryCreateBookmarkedUrl, [url]), + returnValue: _i4.Future.value(), + ) + as _i4.Future); + + @override + _i4.Future startAccessingSecurityScopedResource(String? url) => + (super.noSuchMethod( + Invocation.method(#startAccessingSecurityScopedResource, [url]), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); + + @override + _i4.Future stopAccessingSecurityScopedResource(String? url) => + (super.noSuchMethod( + Invocation.method(#stopAccessingSecurityScopedResource, [url]), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) + as _i4.Future); +} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart deleted file mode 100644 index 542e0a5a87ba..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; -import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_directory.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; - -import 'darwin_scoped_storage_cross_directory_test.mocks.dart'; - -@GenerateMocks([CrossFileDarwinApi]) -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - PigeonOverrides.pigeon_reset(); - }); - - test('exists', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileExists(uri)).thenAnswer( - (_) async => FileExistsResult(exists: true, isDirectory: true), - ); - - final file = DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.exists(), true); - }); - - test('list', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const fileUri = 'fileUri'; - when(mockApi.list(any)).thenAnswer((_) async => [fileUri]); - when(mockApi.fileExists(fileUri)).thenAnswer( - (_) async => FileExistsResult(exists: true, isDirectory: false), - ); - - final dir = DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), - ); - - final List entityUris = await dir - .list(ListParams()) - .map((PlatformXFileEntity entity) => entity.params.uri) - .toList(); - - expect(entityUris, [fileUri]); - }); -} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart deleted file mode 100644 index 0bda183f4440..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ /dev/null @@ -1,229 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; -import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; - -import 'darwin_scoped_storage_cross_file_test.mocks.dart'; - -@GenerateMocks([FileHandle, CrossFileDarwinApi]) -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - PigeonOverrides.pigeon_reset(); - }); - - test('lastModified', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const modificationDate = 123; - when( - mockApi.fileModificationDate(uri), - ).thenAnswer((_) async => modificationDate); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect( - await file.lastModified(), - DateTime.fromMillisecondsSinceEpoch(modificationDate), - ); - }); - - test('length', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const size = 123; - when(mockApi.fileSize(uri)).thenAnswer((_) async => size); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.length(), size); - }); - - group('openRead', () { - test('openRead finishes successfully', () async { - final testBytes = Uint8List.fromList([0, 1, 2]); - - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); - - final mockFileHandle = MockFileHandle(); - setUpFileHandleWithBytes(mockFileHandle, testBytes); - PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { - expect(path, uri); - return mockFileHandle; - }; - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(combineLists(await file.openRead().toList()), testBytes); - }); - - test( - 'openRead finishes successfully with file larger than max array len', - () async { - final testBytes = Uint8List.fromList( - List.filled(DarwinScopedStorageXFile.maxByteArrayLen + 1, 0), - ); - - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); - - final mockFileHandle = MockFileHandle(); - setUpFileHandleWithBytes(mockFileHandle, testBytes); - PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { - expect(path, uri); - return mockFileHandle; - }; - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(combineLists(await file.openRead().toList()), testBytes); - }, - ); - - test('openRead finishes successfully with subset of array', () async { - final testBytes = Uint8List.fromList([0, 0, 0, 1, 1, 1, 0, 0, 0]); - - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); - - final mockFileHandle = MockFileHandle(); - setUpFileHandleWithBytes(mockFileHandle, testBytes); - PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { - expect(path, uri); - return mockFileHandle; - }; - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(combineLists(await file.openRead(3, 6).toList()), [1, 1, 1]); - }); - }); - - test('readAsBytes', () async { - final testBytes = Uint8List.fromList([0, 1, 2]); - - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); - - final mockFileHandle = MockFileHandle(); - when(mockFileHandle.readToEnd()).thenAnswer((_) async => testBytes); - PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { - expect(path, uri); - return mockFileHandle; - }; - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.readAsBytes(), testBytes); - }); - - test('readAsString', () async { - const testString = 'Hello, World!'; - final Uint8List testBytes = utf8.encode(testString); - - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileSize(uri)).thenAnswer((_) async => testBytes.length); - - final mockFileHandle = MockFileHandle(); - setUpFileHandleWithBytes(mockFileHandle, testBytes); - PigeonOverrides.fileHandle_forReadingAtPath = (String path) async { - expect(path, uri); - return mockFileHandle; - }; - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.readAsString(), testString); - }); - - test('canRead', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const canRead = false; - when(mockApi.isReadableFile(uri)).thenAnswer((_) async => canRead); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.canRead(), canRead); - }); - - test('exists', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - when(mockApi.fileExists(uri)).thenAnswer( - (_) async => FileExistsResult(exists: true, isDirectory: false), - ); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.exists(), true); - }); - - test('name', () async { - final mockApi = MockCrossFileDarwinApi(); - const name = 'myfile.txt'; - const uri = 'hello/$name'; - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.name(), name); - }); -} - -void setUpFileHandleWithBytes(MockFileHandle mockFileHandle, Uint8List bytes) { - int offset = 0; - - when(mockFileHandle.seek(any)).thenAnswer((Invocation invocation) async { - offset = invocation.positionalArguments[0] as int; - }); - - when(mockFileHandle.readUpToCount(any)).thenAnswer(( - Invocation invocation, - ) async { - final count = invocation.positionalArguments[0] as int; - final Uint8List nextBytes = bytes.sublist(offset, offset + count); - offset += count; - return nextBytes; - }); -} - -Uint8List combineLists(List lists) { - return Uint8List.fromList( - lists.expand((Uint8List element) => element).toList(), - ); -} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart deleted file mode 100644 index 2d67e03be146..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart +++ /dev/null @@ -1,182 +0,0 @@ -// Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i3; -import 'dart:typed_data' as _i4; - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; -import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i5; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class -// ignore_for_file: invalid_use_of_internal_member - -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { - _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeFileHandle_1 extends _i1.SmartFake implements _i2.FileHandle { - _FakeFileHandle_1(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeFileExistsResult_2 extends _i1.SmartFake - implements _i2.FileExistsResult { - _FakeFileExistsResult_2(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -/// A class which mocks [FileHandle]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockFileHandle extends _i1.Mock implements _i2.FileHandle { - MockFileHandle() { - _i1.throwOnMissingStub(this); - } - - @override - _i2.PigeonInstanceManager get pigeon_instanceManager => - (super.noSuchMethod( - Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_0( - this, - Invocation.getter(#pigeon_instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override - _i3.Future<_i4.Uint8List?> readUpToCount(int? count) => - (super.noSuchMethod( - Invocation.method(#readUpToCount, [count]), - returnValue: _i3.Future<_i4.Uint8List?>.value(), - ) - as _i3.Future<_i4.Uint8List?>); - - @override - _i3.Future<_i4.Uint8List?> readToEnd() => - (super.noSuchMethod( - Invocation.method(#readToEnd, []), - returnValue: _i3.Future<_i4.Uint8List?>.value(), - ) - as _i3.Future<_i4.Uint8List?>); - - @override - _i3.Future seek(int? offset) => - (super.noSuchMethod( - Invocation.method(#seek, [offset]), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i3.Future close() => - (super.noSuchMethod( - Invocation.method(#close, []), - returnValue: _i3.Future.value(), - returnValueForMissingStub: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i2.FileHandle pigeon_copy() => - (super.noSuchMethod( - Invocation.method(#pigeon_copy, []), - returnValue: _FakeFileHandle_1( - this, - Invocation.method(#pigeon_copy, []), - ), - ) - as _i2.FileHandle); -} - -/// A class which mocks [CrossFileDarwinApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockCrossFileDarwinApi extends _i1.Mock - implements _i2.CrossFileDarwinApi { - MockCrossFileDarwinApi() { - _i1.throwOnMissingStub(this); - } - - @override - String get pigeonVar_messageChannelSuffix => - (super.noSuchMethod( - Invocation.getter(#pigeonVar_messageChannelSuffix), - returnValue: _i5.dummyValue( - this, - Invocation.getter(#pigeonVar_messageChannelSuffix), - ), - ) - as String); - - @override - _i3.Future tryCreateBookmarkedUrl(String? url) => - (super.noSuchMethod( - Invocation.method(#tryCreateBookmarkedUrl, [url]), - returnValue: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i3.Future isReadableFile(String? url) => - (super.noSuchMethod( - Invocation.method(#isReadableFile, [url]), - returnValue: _i3.Future.value(false), - ) - as _i3.Future); - - @override - _i3.Future<_i2.FileExistsResult> fileExists(String? url) => - (super.noSuchMethod( - Invocation.method(#fileExists, [url]), - returnValue: _i3.Future<_i2.FileExistsResult>.value( - _FakeFileExistsResult_2( - this, - Invocation.method(#fileExists, [url]), - ), - ), - ) - as _i3.Future<_i2.FileExistsResult>); - - @override - _i3.Future fileModificationDate(String? url) => - (super.noSuchMethod( - Invocation.method(#fileModificationDate, [url]), - returnValue: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i3.Future fileSize(String? url) => - (super.noSuchMethod( - Invocation.method(#fileSize, [url]), - returnValue: _i3.Future.value(), - ) - as _i3.Future); - - @override - _i3.Future> list(String? url) => - (super.noSuchMethod( - Invocation.method(#list, [url]), - returnValue: _i3.Future>.value([]), - ) - as _i3.Future>); -} From c1ddce9cf8cf5997b8d6346656b054085305ac77 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 13:19:03 -0500 Subject: [PATCH 154/398] start of swift tests maybe --- .../Tests/CrossFileDarwinApiTests.swift | 5 + .../darwin/Tests/FileHandleTests.swift | 151 ------------------ .../darwin/Tests/TestProxyAPIRegistrar.swift | 11 -- .../CrossFileDarwinApiImpl.swift | 6 - .../ios/Runner.xcodeproj/project.pbxproj | 8 - .../example/ios/RunnerTests/RunnerTests.swift | 13 +- 6 files changed, 17 insertions(+), 177 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index b3cd65ac71dc..79fb7a2eec89 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -3,3 +3,8 @@ // import Foundation + + +struct A: URL { + +} diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift deleted file mode 100644 index 4fe8e8e92f58..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/FileHandleTests.swift +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Flutter -import Testing - -@testable import cross_file_darwin - -class FileHandleTests { - @Test func forReadingFromUrl() { - let registrar = TestProxyAPIRegistrar() - let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - - let assetFilePath: String = FlutterDartProject.lookupKey(forAsset: "hello.txt") -// let a = Bundle(for: FileHandleTests.self).pat -// forResource: (assetFilePath as NSString).deletingPathExtension, -// withExtension: (assetFilePath as NSString).pathExtension) - let b = Bundle(for: FileHandleTests.self) - let a = b.path(forResource: (assetFilePath as NSString).deletingPathExtension, ofType: (assetFilePath as NSString).pathExtension) - print((assetFilePath as NSString).deletingPathExtension) - print((assetFilePath as NSString).pathExtension) - - //let a = urlForAsset()! - - let instance = try? api.pigeonDelegate.forReadingAtPath(pigeonApi: api, path: a!) - #expect(instance != nil) - } - - // @Test func testReadUpToCount() { - // let registrar = TestProxyAPIRegistrar() - // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - // - // let instance = TestFileHandle() - // let count = 0 - // let value = try? api.pigeonDelegate.readUpToCount( - // pigeonApi: api, pigeonInstance: instance, count: Int64(count)) - // - // XCTAssertEqual(instance.readUpToCountArgs, [count]) - // XCTAssertEqual(value, instance.readUpToCount(count: count)) - // } - // - // @Test func testReadToEnd() { - // let registrar = TestProxyAPIRegistrar() - // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - // - // let instance = TestFileHandle() - // let value = try? api.pigeonDelegate.readToEnd(pigeonApi: api, pigeonInstance: instance) - // - // XCTAssertTrue(instance.readToEndCalled) - // XCTAssertEqual(value, instance.readToEnd()) - // } - // - // @Test func testSeek() { - // let registrar = TestProxyAPIRegistrar() - // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - // - // let instance = TestFileHandle() - // let offset = 0 - // let value = try? api.pigeonDelegate.seek( - // pigeonApi: api, pigeonInstance: instance, offset: offset) - // - // XCTAssertEqual(instance.seekArgs, [offset]) - // XCTAssertEqual(value, instance.seek(offset: offset)) - // } - // - // @Test func testClose() { - // let registrar = TestProxyAPIRegistrar() - // let api = registrar.apiDelegate.pigeonApiFileHandle(registrar) - // - // let instance = TestFileHandle() - // try? api.pigeonDelegate.close(pigeonApi: api, pigeonInstance: instance) - // - // XCTAssertTrue(instance.closeCalled) - // } - - func urlForAsset() -> URL? { - let assetFilePath: String? = FlutterDartProject.lookupKey(forAsset: "assets/index.html") - - guard let assetFilePath = assetFilePath else { - return nil - } - -// print("hello") -// print(FlutterDartProject.lookupKey(forAsset: "assets/index.html")) - - var url: URL? = TestBundle().url( - forResource: (assetFilePath as NSString).deletingPathExtension, - withExtension: (assetFilePath as NSString).pathExtension) - - print(url ?? "open") - - #if os(macOS) - // See https://github.com/flutter/flutter/issues/135302 - // TODO(stuartmorgan): Remove this if the asset APIs are adjusted to work better for macOS. - if url == nil { - url = URL(string: assetFilePath, relativeTo: bundle.bundleURL) - } - #endif - - return url - } -} - -class TestBundle: Bundle, @unchecked Sendable { - override func url(forResource name: String?, withExtension ext: String?) -> URL? { - return URL(string: "assets/index.html")! - } -} - -class TestFileHandle: FileHandle, @unchecked Sendable { - var readUpToCountArgs: [AnyHashable?]? = nil - var readToEndCalled = false - var seekArgs: [AnyHashable?]? = nil - var closeCalled = false - - // func read(upToCount count: Int) throws -> Data? { - // readUpToCountArgs = [count] - // return byteArrayOf(0xA1.toByte()) - // } - - // func hello(apple: TestFileHandle) throws -> Data? { - // readToEndCalled = true - // } - - override func seek(toOffset offset: UInt64) throws { - seekArgs = [offset] - } - - override func close() throws { - closeCalled = true - } -} - -//extension TestFileHandle { -// @_dynamicReplacement(for:readToEnd()) -// dynamic func a() throws -> Data? { -// -// } -// -// @_dynamicReplacement(for:close()) -// dynamic func b() throws { -// -// } -//} - -//extension TestFileHandle { -// @objc override func readToEnd() throws -> Data? { -// readToEndCalled = true -// } -//} diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift deleted file mode 100644 index a897f9008968..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@testable import cross_file_darwin - -class TestProxyAPIRegistrar: ProxyAPIRegistrar { - init() { - super.init(binaryMessenger: TestBinaryMessenger()) - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 62284cbb3b70..29753fe1d55b 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -14,12 +14,6 @@ import Foundation /// Implementation of `CrossFileDarwinApi`. class CrossFileDarwinApiImpl: CrossFileDarwinApi { - let fileManager: FileManager - - init(fileManager: FileManager = FileManager.default) { - self.fileManager = fileManager - } - func tryCreateBookmarkedUrl(url: String) throws -> String? { let nativeUrl = URL(fileURLWithPath: url) if nativeUrl.startAccessingSecurityScopedResource() { diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 966c37e3b23e..eab407d41105 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -15,9 +15,7 @@ 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */; }; 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */; }; - 8F2171F82F21A5270014CE68 /* FileHandleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */; }; 8F2171FB2F2295120014CE68 /* TestBinaryMessenger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */; }; - 8F2171FC2F2295120014CE68 /* TestProxyAPIRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -61,9 +59,7 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; - 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FileHandleTests.swift; path = ../../darwin/Tests/FileHandleTests.swift; sourceTree = SOURCE_ROOT; }; 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestBinaryMessenger.swift; path = ../../darwin/Tests/TestBinaryMessenger.swift; sourceTree = SOURCE_ROOT; }; - 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = ../../darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = SOURCE_ROOT; }; 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -101,9 +97,7 @@ isa = PBXGroup; children = ( 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */, - 8F2171FA2F2295120014CE68 /* TestProxyAPIRegistrar.swift */, 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */, - 8F2171F62F21A5270014CE68 /* FileHandleTests.swift */, 331C807B294A618700263BE5 /* RunnerTests.swift */, ); path = RunnerTests; @@ -385,9 +379,7 @@ files = ( 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */, - 8F2171F82F21A5270014CE68 /* FileHandleTests.swift in Sources */, 8F2171FB2F2295120014CE68 /* TestBinaryMessenger.swift in Sources */, - 8F2171FC2F2295120014CE68 /* TestProxyAPIRegistrar.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift index ea8b210b8523..3c40eba6e449 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift @@ -1,4 +1,15 @@ -import Flutter +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + import Testing import UIKit From d97486715dc506b89f7b3f928bad390bd34c2f05 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 22:31:01 -0500 Subject: [PATCH 155/398] create some semblance of unit tests --- .../Tests/CrossFileDarwinApiTests.swift | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 79fb7a2eec89..0b752118baec 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -1,10 +1,48 @@ -// -// Created by Maurice Parrish on 1/21/26. -// +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -import Foundation +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif +import Testing +import cross_file_darwin +import UIKit -struct A: URL { +@testable import cross_file_darwin + +struct CrossFileDarwinApiTests { + func createTempTestFile() throws -> URL { + let fileManager = FileManager.default + let tempDirectory = fileManager.temporaryDirectory + let fileName = UUID().uuidString + ".txt" + let fileURL = tempDirectory.appendingPathComponent(fileName) + + try "Hello, World!".write(to: fileURL, atomically: true, encoding: .utf8) + + return fileURL + } + + @Test func startAccessingSecurityScopedResource() throws { + let testFileURL = try createTempTestFile() + + let api = CrossFileDarwinApiImpl() + let canAccess = try api.startAccessingSecurityScopedResource(url: testFileURL.path) + + #expect(canAccess) + } + @Test func tryCreateBookmarkedUrl() throws { + let testFileURL = try createTempTestFile() + + let api = CrossFileDarwinApiImpl() + let bookmarkedURLString = try! api.tryCreateBookmarkedUrl(url: testFileURL.path)! + + #expect(URL(fileURLWithPath: bookmarkedURLString) == testFileURL) + } } From 88c1c8f064e0677daecc79a5be24601252522649 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 22:33:05 -0500 Subject: [PATCH 156/398] bookmark doesn't call access --- .../CrossFileDarwinApiImpl.swift | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 29753fe1d55b..4891b17697e8 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -16,21 +16,17 @@ import Foundation class CrossFileDarwinApiImpl: CrossFileDarwinApi { func tryCreateBookmarkedUrl(url: String) throws -> String? { let nativeUrl = URL(fileURLWithPath: url) - if nativeUrl.startAccessingSecurityScopedResource() { - defer { nativeUrl.stopAccessingSecurityScopedResource() } + let data = try nativeUrl.bookmarkData( + options: [], + includingResourceValuesForKeys: nil, + relativeTo: nil + ) - let data = try nativeUrl.bookmarkData( - options: [], - includingResourceValuesForKeys: nil, - relativeTo: nil - ) + var isStale: Bool = true + let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - var isStale: Bool = true - let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - - if !isStale { - return bookmarkedUrl.path - } + if !isStale { + return bookmarkedUrl.path } return nil From 712ae02790d5b87a8a66d6183dc5c16905c6f2b9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 22:51:34 -0500 Subject: [PATCH 157/398] ios and macos tests --- .../Tests/CrossFileDarwinApiTests.swift | 7 ++-- .../darwin/Tests/TestBinaryMessenger.swift | 33 ------------------- .../ios/Runner.xcodeproj/project.pbxproj | 8 ++--- .../macos/Runner.xcodeproj/project.pbxproj | 13 +++++--- .../macos/RunnerTests/RunnerTests.swift | 28 ---------------- 5 files changed, 17 insertions(+), 72 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift delete mode 100644 packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 0b752118baec..288c4c01e663 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -11,8 +11,6 @@ #endif import Testing -import cross_file_darwin -import UIKit @testable import cross_file_darwin @@ -34,7 +32,12 @@ struct CrossFileDarwinApiTests { let api = CrossFileDarwinApiImpl() let canAccess = try api.startAccessingSecurityScopedResource(url: testFileURL.path) + // Only returns true on iOS. +#if os(iOS) #expect(canAccess) +#endif + + #expect(try String(contentsOf: testFileURL, encoding: .utf8) == "Hello, World!") } @Test func tryCreateBookmarkedUrl() throws { diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift deleted file mode 100644 index c40727acb44d..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/TestBinaryMessenger.swift +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -class TestBinaryMessenger: NSObject, FlutterBinaryMessenger { - func send(onChannel channel: String, message: Data?) { - - } - - func send( - onChannel channel: String, message: Data?, binaryReply callback: FlutterBinaryReply? = nil - ) { - - } - - func setMessageHandlerOnChannel( - _ channel: String, binaryMessageHandler handler: FlutterBinaryMessageHandler? = nil - ) -> FlutterBinaryMessengerConnection { - return 0 - } - - func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) { - - } -} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index eab407d41105..ff7edcc631a7 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */; }; 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */; }; - 8F2171FB2F2295120014CE68 /* TestBinaryMessenger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -59,7 +58,6 @@ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; - 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestBinaryMessenger.swift; path = ../../darwin/Tests/TestBinaryMessenger.swift; sourceTree = SOURCE_ROOT; }; 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -96,7 +94,6 @@ 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 8F2171F92F2295120014CE68 /* TestBinaryMessenger.swift */, 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */, 331C807B294A618700263BE5 /* RunnerTests.swift */, ); @@ -317,10 +314,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -379,7 +380,6 @@ files = ( 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */, - 8F2171FB2F2295120014CE68 /* TestBinaryMessenger.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index e519e5c8c25d..ce4c04d9e025 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -22,12 +22,12 @@ /* Begin PBXBuildFile section */ 1E3F930A949E6BF1A392A157 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */; }; - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 8FB3B0B92F3D820100A1CEDF /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */; }; 9365FDE22965FC1D9207E2E0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63A129979C19E770A95C46BB /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ @@ -64,7 +64,6 @@ /* Begin PBXFileReference section */ 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cross_file_darwin_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -85,6 +84,7 @@ 6E84AA1E5316F40ABCA87AF9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 7255794ECF94B4FB91F39D79 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; 95E600C17773E34356453E89 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; @@ -113,7 +113,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -195,7 +195,6 @@ AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */, 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -391,10 +390,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -429,7 +432,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + 8FB3B0B92F3D820100A1CEDF /* CrossFileDarwinApiTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index bd120c3c0b5d..000000000000 --- a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,28 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -@testable import cross_file_darwin - -// This demonstrates a simple unit test of the Swift portion of this plugin's implementation. -// -// See https://developer.apple.com/documentation/xctest for more information about using XCTest. - -class RunnerTests: XCTestCase { - - func testGetPlatformVersion() { - let plugin = CrossFileDarwinPlugin() - - let call = FlutterMethodCall(methodName: "getPlatformVersion", arguments: []) - - let resultExpectation = expectation(description: "result block must be called.") - plugin.handle(call) { result in - XCTAssertEqual( - result as! String, - "macOS " + ProcessInfo.processInfo.operatingSystemVersionString) - resultExpectation.fulfill() - } - waitForExpectations(timeout: 1) - } - -} From f7a242e87cc135e84573176ea42e7cb9dd748607 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 23:03:57 -0500 Subject: [PATCH 158/398] darwin usese uri and not file path --- .../apiImplementations/CrossFileDarwinApiImpl.swift | 8 ++++---- .../cross_file_darwin/lib/cross_file_darwin.dart | 4 ++-- .../cross_file_darwin/lib/src/darwin_cross_directory.dart | 6 ++++++ .../cross_file_darwin/lib/src/darwin_cross_file.dart | 6 ++++++ 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 4891b17697e8..d856fef30b83 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -15,7 +15,7 @@ import Foundation /// Implementation of `CrossFileDarwinApi`. class CrossFileDarwinApiImpl: CrossFileDarwinApi { func tryCreateBookmarkedUrl(url: String) throws -> String? { - let nativeUrl = URL(fileURLWithPath: url) + let nativeUrl = URL(string: url)! let data = try nativeUrl.bookmarkData( options: [], includingResourceValuesForKeys: nil, @@ -26,17 +26,17 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) if !isStale { - return bookmarkedUrl.path + return bookmarkedUrl.absoluteString } return nil } func startAccessingSecurityScopedResource(url: String) throws -> Bool { - return URL(fileURLWithPath: url).startAccessingSecurityScopedResource() + return URL(string: url)!.startAccessingSecurityScopedResource() } func stopAccessingSecurityScopedResource(url: String) throws { - URL(fileURLWithPath: url).stopAccessingSecurityScopedResource() + URL(string: url)!.stopAccessingSecurityScopedResource() } } diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 091dad830432..fb305b8803c0 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -6,6 +6,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXFileEntity; export 'src/cross_file_darwin.dart'; -export 'src/darwin_cross_directory.dart' show DarwinXDirectoryExtension; -export 'src/darwin_cross_file.dart' show DarwinXFileExtension; +export 'src/darwin_cross_directory.dart' show DarwinXDirectoryCreationParams, DarwinXDirectoryExtension; +export 'src/darwin_cross_file.dart' show DarwinXFileCreationParams, DarwinXFileExtension; export 'src/security_scoped_resource.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart index d4b93945f4f1..43c2eb34fe74 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart @@ -21,6 +21,12 @@ base class DarwinXDirectoryCreationParams extends IOXDirectoryCreationParams { @visibleForTesting CrossFileDarwinApi? api, }) : api = api ?? CrossFileDarwinApi(); + DarwinXDirectoryCreationParams.fromFilePath({ + required String path, + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(), + super(uri: 'file:///$path'); + /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart index 5396a2b6b8ee..c6104b3ec909 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart @@ -21,6 +21,12 @@ base class DarwinXFileCreationParams extends IOXFileCreationParams { @visibleForTesting CrossFileDarwinApi? api, }) : api = api ?? CrossFileDarwinApi(); + DarwinXFileCreationParams.fromFilePath({ + required String path, + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(), + super(uri: 'file:///$path'); + /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; From 55aa297600cdd49f5eaeedceac898810498a659a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 11 Feb 2026 23:19:22 -0500 Subject: [PATCH 159/398] update tests --- .../darwin/Tests/CrossFileDarwinApiTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 288c4c01e663..300e79a710db 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -30,7 +30,7 @@ struct CrossFileDarwinApiTests { let testFileURL = try createTempTestFile() let api = CrossFileDarwinApiImpl() - let canAccess = try api.startAccessingSecurityScopedResource(url: testFileURL.path) + let canAccess = try api.startAccessingSecurityScopedResource(url: testFileURL.absoluteString) // Only returns true on iOS. #if os(iOS) @@ -44,7 +44,7 @@ struct CrossFileDarwinApiTests { let testFileURL = try createTempTestFile() let api = CrossFileDarwinApiImpl() - let bookmarkedURLString = try! api.tryCreateBookmarkedUrl(url: testFileURL.path)! + let bookmarkedURLString = try! api.tryCreateBookmarkedUrl(url: testFileURL.absoluteString)! #expect(URL(fileURLWithPath: bookmarkedURLString) == testFileURL) } From aac1e0a1dcfac385270dfb3f2f1f719cece687c4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 12:51:22 -0500 Subject: [PATCH 160/398] update io and platform interface for uri --- .../example/ios/Runner.xcodeproj/project.pbxproj | 4 ---- .../lib/src/darwin_cross_directory.dart | 6 ------ .../cross_file_darwin/lib/src/darwin_cross_file.dart | 6 ------ .../cross_file_io/lib/src/io_cross_directory.dart | 10 +++++----- .../cross_file_io/lib/src/io_cross_file.dart | 5 +++-- .../cross_file_io/test/io_cross_directory_test.dart | 2 +- 6 files changed, 9 insertions(+), 24 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index ff7edcc631a7..3a080bfd2891 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -314,14 +314,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart index 43c2eb34fe74..d4b93945f4f1 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_directory.dart @@ -21,12 +21,6 @@ base class DarwinXDirectoryCreationParams extends IOXDirectoryCreationParams { @visibleForTesting CrossFileDarwinApi? api, }) : api = api ?? CrossFileDarwinApi(); - DarwinXDirectoryCreationParams.fromFilePath({ - required String path, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(), - super(uri: 'file:///$path'); - /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart index c6104b3ec909..5396a2b6b8ee 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_cross_file.dart @@ -21,12 +21,6 @@ base class DarwinXFileCreationParams extends IOXFileCreationParams { @visibleForTesting CrossFileDarwinApi? api, }) : api = api ?? CrossFileDarwinApi(); - DarwinXFileCreationParams.fromFilePath({ - required String path, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(), - super(uri: 'file:///$path'); - /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart index 80eaac1e9b3b..380ce720751c 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -14,11 +14,11 @@ import 'io_cross_file.dart'; base class IOXDirectoryCreationParams extends PlatformXDirectoryCreationParams { /// Constructs an [IOXDirectoryCreationParams]. IOXDirectoryCreationParams({required String uri}) - : this.fromFile(Directory(uri)); + : this.fromDirectory(Directory.fromUri(Uri.parse(uri))); /// Constructs an [IOXDirectoryCreationParams] from a [Directory]. - IOXDirectoryCreationParams.fromFile(this.directory) - : super(uri: directory.path); + IOXDirectoryCreationParams.fromDirectory(this.directory) + : super(uri: directory.uri.toString()); /// Constructs an [IOXDirectoryCreationParams] from a [PlatformXDirectoryCreationParams]. factory IOXDirectoryCreationParams.fromCreationParams( @@ -57,10 +57,10 @@ base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { switch (entity) { case final Directory directory: yield IOXDirectory( - PlatformXDirectoryCreationParams(uri: directory.path), + IOXDirectoryCreationParams.fromDirectory(directory), ); case final File file: - yield IOXFile(PlatformXFileCreationParams(uri: file.path)); + yield IOXFile(IOXFileCreationParams.fromFile(file)); } } } diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index cc1da0ef3fba..8857bce6b68a 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -13,10 +13,11 @@ import 'package:path/path.dart' as path; @immutable base class IOXFileCreationParams extends PlatformXFileCreationParams { /// Constructs an [IOXFileCreationParams]. - IOXFileCreationParams({required String uri}) : this.fromFile(File(uri)); + IOXFileCreationParams({required String uri}) + : this.fromFile(File.fromUri(Uri.parse(uri))); /// Constructs an [IOXFileCreationParams] from a [File]. - IOXFileCreationParams.fromFile(this.file) : super(uri: file.path); + IOXFileCreationParams.fromFile(this.file) : super(uri: file.uri.toString()); /// Constructs an [IOXFileCreationParams] from a [PlatformXFileCreationParams]. factory IOXFileCreationParams.fromCreationParams( diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart index 5bfe565ff3d4..94ae20734561 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -37,7 +37,7 @@ void main() { (PlatformXFileEntity entity) => entity.params.uri, ), (await testDirectory.list().toList()).map( - (FileSystemEntity entity) => entity.path, + (FileSystemEntity entity) => entity.uri.toString(), ), ); }); From 4610e8346fcb39b808812203155567604c2e4133 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:10:16 -0500 Subject: [PATCH 161/398] update web impl --- .../cross_file_web/example/lib/main.dart | 91 +++++++++++++------ .../cross_file_web/example/pubspec.yaml | 14 ++- 2 files changed, 75 insertions(+), 30 deletions(-) diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index c66ed1242f9c..43b332515d93 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -18,23 +18,52 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); - if (!context.mounted) { - return; - } - if (file case final XFile file) { - switch (mime.lookupMimeType(file.path)) { + final String filename = await file.name() ?? file.uri; + + switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): - await showDialog( - context: context, - builder: (BuildContext context) => TextDisplay(file), - ); - case final String mimeType when mimeType.startsWith('image'): - case final String mimeType when mimeType.startsWith('application'): - case null: - debugPrint('Unsupported file type: ${file.path}'); + final String fileContents = await file.readAsString(); + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(filename: filename, fileContents: fileContents), + ); + } + case _: + debugPrint('File Uri: ${file.uri}'); + debugPrint('Filename: $filename'); + debugPrint('Can Read File: ${await file.canRead()}'); + debugPrint('File Length: ${await file.length()}'); + debugPrint('File Last Modified: ${await file.lastModified()}'); return; } + } else { + debugPrint('No file selected.'); + } + } + + Future _openDirectory() async { + final XDirectory? directory = await getDirectoryPath(); + + if (directory != null) { + debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory exists: ${await directory.exists()}'); + + debugPrint('List of Entities:'); + await for (final XFileEntity entity in directory.list()) { + switch (entity) { + case final XFile file: + final String filename = await file.name() ?? file.uri; + debugPrint('\tFile: $filename'); + debugPrint('\t\tFile Length: ${await file.length()}'); + case final XDirectory directory: + debugPrint('\tDirectory: ${directory.uri}'); + } + } + } else { + debugPrint('No directory selected.'); } } @@ -57,6 +86,14 @@ class FileOpenScreen extends StatelessWidget { child: const Text('Open File'), onPressed: () => _openFile(context), ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open Directory'), + onPressed: () => _openDirectory(), + ), ], ), ), @@ -67,28 +104,24 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay(this.file, {super.key}); + const TextDisplay({ + super.key, + required this.filename, + required this.fileContents, + }); - /// The file. - final XFile file; + /// The name of the file. + final String filename; + + /// The contents of the file. + final String fileContents; @override Widget build(BuildContext context) { return AlertDialog( - title: Text(file.path), + title: Text(filename), content: Scrollbar( - child: SingleChildScrollView( - child: FutureBuilder( - future: file.readAsString(), - builder: (_, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return Text(snapshot.data!); - } else { - return const CircularProgressIndicator(); - } - }, - ), - ), + child: SingleChildScrollView(child: Text(fileContents)), ), actions: [ TextButton( diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index 55f86e8150e1..bde81c0eafd7 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -7,7 +7,10 @@ environment: dependencies: file_selector: - path: ../../../file_selector/file_selector + git: + url: https://github.com/bparrishMines/packages + ref: new_file_selector + path: packages/file_selector/file_selector flutter: sdk: flutter mime: ^2.0.0 @@ -18,3 +21,12 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + +dependency_overrides: + cross_file_web: + # When depending on this package from a real application you should use: + # cross_file_darwin: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ From 9be385ca51a83a05cc88308b835a9867e2a9af90 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:20:11 -0500 Subject: [PATCH 162/398] update cross file dep --- packages/cross_file/cross_file_web/pubspec.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index a6ec6bbd0c87..4de66a004b6f 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -17,7 +17,10 @@ flutter: dependencies: cross_file_platform_interface: - path: ../cross_file_platform_interface + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface flutter: sdk: flutter flutter_web_plugins: From 1402e674cd03973e42e206dc77d38806fa7ed94b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:26:06 -0500 Subject: [PATCH 163/398] add filename --- packages/cross_file/cross_file_web/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 4de66a004b6f..bfbe756d2d49 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -14,6 +14,7 @@ flutter: platforms: web: pluginClass: CrossFileWeb + fileName: cross_file_web.dart dependencies: cross_file_platform_interface: From 551f04bdc9a32e28fd4c13aa03614a7629a1e8d3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 13:39:17 -0500 Subject: [PATCH 164/398] update web with factories --- .../cross_file_web/lib/cross_file_web.dart | 7 +---- .../lib/src/web_cross_file.dart | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 0a1efc6f88aa..d25dce016798 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -3,9 +3,4 @@ // found in the LICENSE file. export 'src/cross_file_web.dart'; -export 'src/web_cross_file.dart' - show - BlobWebXFileCreationParams, - UrlWebXFileCreationParams, - WebXFileCreationParams, - WebXFileExtension; +export 'src/web_cross_file.dart' show WebXFileCreationParams, WebXFileExtension; diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index f895bc76c770..24a394728856 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -16,6 +16,32 @@ sealed class WebXFileCreationParams extends PlatformXFileCreationParams { /// Constructs a [WebXFileCreationParams]. const WebXFileCreationParams({required super.uri, this.testOverrides}); + /// Constructs a [WebXFileCreationParams] with an object url. + factory WebXFileCreationParams.fromObjectUrl({ + required String objectUrl, + @visibleForTesting XFileTestOverrides? testOverrides, + }) => UrlWebXFileCreationParams( + objectUrl: objectUrl, + testOverrides: testOverrides, + ); + + /// Constructs a [WebXFileCreationParams] with a [Blob]. + /// + /// Creates an Object URL using the provided blob. See [URL.createObjectURL] + /// + /// `autoRevokeObjectUrl`: Whether the unique object url obtained created with + /// [blob] should be revoked when this instance is garbage collected. See + /// [URL.revokeObjectURL]. + factory WebXFileCreationParams.fromBlob( + Blob blob, { + bool autoRevokeObjectUrl = true, + @visibleForTesting XFileTestOverrides? testOverrides, + }) => BlobWebXFileCreationParams( + blob, + autoRevokeObjectUrl: autoRevokeObjectUrl, + testOverrides: testOverrides, + ); + /// Overrides some functions to allow testing. @visibleForTesting final XFileTestOverrides? testOverrides; From e013d143e523b9353387532d6f875f86238e420c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:11:34 -0500 Subject: [PATCH 165/398] add convenient method for xfile --- .../cross_file/lib/src/cross_directory.dart | 14 +++++++--- .../cross_file/lib/src/cross_file.dart | 14 +++++++--- .../src/scoped_storage_cross_directory.dart | 4 +-- .../lib/src/scoped_storage_cross_file.dart | 9 ++++--- .../cross_file/test/cross_directory_test.dart | 4 +-- .../cross_file/test/cross_file_test.dart | 16 +++++------ .../scoped_storage_cross_directory_test.dart | 4 +-- .../test/scoped_storage_cross_file_test.dart | 16 +++++------ .../cross_file_web/example/lib/main.dart | 3 ++- .../test/web_cross_file_test.dart | 27 ++++++++++--------- 10 files changed, 64 insertions(+), 47 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 2adbb3207e31..4ae25fa3e676 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -25,7 +25,7 @@ import 'scoped_storage_cross_file.dart'; /// the dart:io implementation of `cross_file`: /// /// ```dart -/// final XDirectory dir = XFile('my/docs/'); +/// final XDirectory dir = XDirectory.fromUri(Uri.directory('my/docs/.')); /// /// final IOXDirectoryExtension? ioExtension = file.maybeGetExtension(); /// if (ioExtension != null) { @@ -36,11 +36,17 @@ import 'scoped_storage_cross_file.dart'; class XDirectory extends XFileEntity { /// Constructs a [XDirectory]. /// - /// See [XDirectory.fromCreationParams] for setting parameters for a - /// specific platform. - XDirectory(String uri) + /// See [XDirectory.fromCreationParams] for setting parameters for a specific + /// platform. + XDirectory({required String uri}) : this.fromCreationParams(PlatformXDirectoryCreationParams(uri: uri)); + /// Constructs a [XDirectory]. + /// + /// See [XDirectory.fromCreationParams] for setting parameters for a specific + /// platform. + XDirectory.fromUri(Uri uri) : this(uri: uri.toString()); + /// Constructs a [XDirectory] from creation params for a specific platform. /// /// {@template cross_file.XDirectory.fromCreationParams} diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 23a6d136ecb4..aa09a60ff9fb 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -22,7 +22,7 @@ import 'cross_file_entity.dart'; /// the dart:io implementation of `cross_file`: /// /// ```dart -/// final XFile file = XFile('my/file.txt'); +/// final XFile file = XFile.fromUri(Uri.file('my/file.txt')); /// /// final IOXFileExtension? ioExtension = file.maybeGetExtension(); /// if (ioExtension != null) { @@ -33,11 +33,17 @@ import 'cross_file_entity.dart'; class XFile extends XFileEntity { /// Constructs a [XFile]. /// - /// See [XFile.fromCreationParams] for setting parameters for a - /// specific platform. - XFile(String uri) + /// See [XFile.fromCreationParams] for setting parameters for a specific + /// platform. + XFile({required String uri}) : this.fromCreationParams(PlatformXFileCreationParams(uri: uri)); + /// Constructs a [XFile]. + /// + /// See [XFile.fromCreationParams] for setting parameters for a specific + /// platform. + XFile.fromUri(Uri uri) : this(uri: uri.toString()); + /// Constructs a [XFile] from creation params for a specific platform. /// /// {@template cross_file.XFile.fromCreationParams} diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index a6644f78036e..daf69b5327ef 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -21,7 +21,7 @@ import 'cross_directory.dart'; /// the Android implementation of `cross_file`: /// /// ```dart -/// final ScopedStorageXDirectory directory = XDirectory('my/dir'); +/// final ScopedStorageXDirectory directory = ScopedStorageXDirectory(uri: 'context://my/dir'); /// /// final AndroidScopedStorageXDirectoryExtension? androidExtension = /// file.maybeGetExtension(); @@ -35,7 +35,7 @@ class ScopedStorageXDirectory extends XDirectory { /// /// See [ScopedStorageXDirectory.fromCreationParams] for setting parameters /// for a specific platform. - ScopedStorageXDirectory(String uri) + ScopedStorageXDirectory({required String uri}) : this.fromCreationParams( PlatformScopedStorageXDirectoryCreationParams(uri: uri), ); diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 870e8c8ec072..2eb2fe2785f4 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -20,7 +20,7 @@ import 'cross_file.dart'; /// the Android implementation of `cross_file`: /// /// ```dart -/// final ScopedStorageXFile file = XFile('context://my/file.txt'); +/// final ScopedStorageXFile file = ScopedStorageXFile(uri: 'context://my/file.txt'); /// /// final AndroidScopedStorageXFileExtension? androidExtension = /// file.maybeGetExtension(); @@ -34,7 +34,7 @@ class ScopedStorageXFile extends XFile { /// /// See [ScopedStorageXFile.fromCreationParams] for setting parameters /// for a specific platform. - ScopedStorageXFile(String uri) + ScopedStorageXFile({required String uri}) : this.fromCreationParams( PlatformScopedStorageXFileCreationParams(uri: uri), ); @@ -63,8 +63,9 @@ class ScopedStorageXFile extends XFile { ) : this.fromPlatform(PlatformScopedStorageXFile(params)); /// Constructs a [ScopedStorageXFile] from a specific platform implementation. - const ScopedStorageXFile.fromPlatform(PlatformScopedStorageXFile super.platform) - : super.fromPlatform(); + const ScopedStorageXFile.fromPlatform( + PlatformScopedStorageXFile super.platform, + ) : super.fromPlatform(); @override PlatformScopedStorageXFile get platform => diff --git a/packages/cross_file/cross_file/test/cross_directory_test.dart b/packages/cross_file/cross_file/test/cross_directory_test.dart index 2a1bb5633bcc..a368ce1cd288 100644 --- a/packages/cross_file/cross_file/test/cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/cross_directory_test.dart @@ -17,7 +17,7 @@ void main() { TestXDirectory(params, onExists: () async => exists), ); - final directory = XDirectory('uri'); + final directory = XDirectory(uri: 'uri'); expect(await directory.exists(), exists); }); @@ -36,7 +36,7 @@ void main() { ), ); - final directory = XDirectory('uri'); + final directory = XDirectory(uri: 'uri'); final List directoryEntities = await directory .list() diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart index 04788baf2b9a..94aed4f5f023 100644 --- a/packages/cross_file/cross_file/test/cross_file_test.dart +++ b/packages/cross_file/cross_file/test/cross_file_test.dart @@ -20,7 +20,7 @@ void main() { TestXFile(params, onLastModified: () async => lastModified), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.lastModified(), lastModified); }); @@ -32,7 +32,7 @@ void main() { TestXFile(params, onLength: () async => length), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.length(), length); }); @@ -46,7 +46,7 @@ void main() { TestXFile(params, onOpenRead: () => Stream.fromIterable(data)), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.openRead().toList(), data); }); @@ -58,7 +58,7 @@ void main() { TestXFile(params, onReadAsBytes: () async => bytes), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.readAsBytes(), bytes); }); @@ -73,7 +73,7 @@ void main() { ), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.readAsString(), message); }); @@ -85,7 +85,7 @@ void main() { TestXFile(params, onCanRead: () async => canRead), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.canRead(), canRead); }); @@ -97,7 +97,7 @@ void main() { TestXFile(params, onExists: () async => exists), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.exists(), exists); }); @@ -109,7 +109,7 @@ void main() { TestXFile(params, onName: () async => name), ); - final file = XFile('uri'); + final file = XFile(uri: 'uri'); expect(await file.name(), name); }); diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 43e4be0af264..9d8b4ddc4f44 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -21,7 +21,7 @@ void main() { ), ); - final directory = ScopedStorageXDirectory('uri'); + final directory = ScopedStorageXDirectory(uri: 'uri'); expect(await directory.exists(), exists); }); @@ -45,7 +45,7 @@ void main() { ), ); - final directory = ScopedStorageXDirectory('uri'); + final directory = ScopedStorageXDirectory(uri: 'uri'); final List directoryEntities = await directory .list() diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart index b15731d423df..dbb729be6fc6 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart @@ -24,7 +24,7 @@ void main() { ), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.lastModified(), lastModified); }); @@ -37,7 +37,7 @@ void main() { TestScopedStorageXFile(params, onLength: () async => length), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.length(), length); }); @@ -55,7 +55,7 @@ void main() { ), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.openRead().toList(), data); }); @@ -71,7 +71,7 @@ void main() { ), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.readAsBytes(), bytes); }); @@ -88,7 +88,7 @@ void main() { ), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.readAsString(), message); }); @@ -101,7 +101,7 @@ void main() { TestScopedStorageXFile(params, onCanRead: () async => canRead), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.canRead(), canRead); }); @@ -114,7 +114,7 @@ void main() { TestScopedStorageXFile(params, onExists: () async => exists), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.exists(), exists); }); @@ -127,7 +127,7 @@ void main() { TestScopedStorageXFile(params, onName: () async => name), ); - final file = ScopedStorageXFile('uri'); + final file = ScopedStorageXFile(uri: 'uri'); expect(await file.name(), name); }); diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index 43b332515d93..cadb2349f373 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -17,8 +17,9 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); + print('here: ${file?.uri}'); - if (file case final XFile file) { + if (file != null) { final String filename = await file.name() ?? file.uri; switch (mime.lookupMimeType(filename)) { diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index 7760784cb93b..d64a68bfa51a 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -82,7 +82,7 @@ void main() { group('Create with File', () { test('lastModified', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect( await file.lastModified(), @@ -91,49 +91,49 @@ void main() { }); test('length', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.length(), testFile.size); }); test('openRead', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.openRead().first, testFileBytes); }); test('openRead with partial data', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); }); test('readAsBytes', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.readAsBytes(), testFileBytes); }); test('readAsString', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.readAsString(), testFileStringContents); }); test('canRead', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.canRead(), true); }); test('exists', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.exists(), true); }); test('name', () async { - final file = PlatformXFile(BlobWebXFileCreationParams(testFile)); + final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); expect(await file.name(), testFile.name); }); @@ -144,7 +144,7 @@ void main() { group('XFile download', () { test('creates a DOM container', () async { - final file = WebXFile(BlobWebXFileCreationParams(testFile)); + final file = WebXFile(WebXFileCreationParams.fromBlob(testFile)); await file.download(''); @@ -156,7 +156,7 @@ void main() { }); test('create anchor element', () async { - final file = WebXFile(BlobWebXFileCreationParams(testFile)); + final file = WebXFile(WebXFileCreationParams.fromBlob(testFile)); await file.download('path'); @@ -187,7 +187,10 @@ void main() { ); final file = WebXFile( - BlobWebXFileCreationParams(testFile, testOverrides: testOverrides), + WebXFileCreationParams.fromBlob( + testFile, + testOverrides: testOverrides, + ), ); var clicked = false; From c935c984c622b89fa5b7594d77f8eaefa6cda083 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:18:28 -0500 Subject: [PATCH 166/398] update example docs --- packages/cross_file/cross_file/lib/src/cross_directory.dart | 4 ++-- packages/cross_file/cross_file/lib/src/cross_file.dart | 4 ++-- .../cross_file/lib/src/scoped_storage_cross_file.dart | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 4ae25fa3e676..636b7f2d781c 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -25,7 +25,7 @@ import 'scoped_storage_cross_file.dart'; /// the dart:io implementation of `cross_file`: /// /// ```dart -/// final XDirectory dir = XDirectory.fromUri(Uri.directory('my/docs/.')); +/// final XDirectory dir = XDirectory.fromUri(Uri.directory('/my/docs/.')); /// /// final IOXDirectoryExtension? ioExtension = file.maybeGetExtension(); /// if (ioExtension != null) { @@ -54,7 +54,7 @@ class XDirectory extends XFileEntity { /// the dart:io implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformXDirectoryCreationParams(uri: 'my/docs/'); + /// var params = const PlatformXDirectoryCreationParams(uri: 'file:///my/docs/'); /// /// if (CrossFilePlatform.instance is CrossFileIO) { /// params = IOXDirectoryCreationParams.fromCreationParams( diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index aa09a60ff9fb..a4213fc405b1 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -22,7 +22,7 @@ import 'cross_file_entity.dart'; /// the dart:io implementation of `cross_file`: /// /// ```dart -/// final XFile file = XFile.fromUri(Uri.file('my/file.txt')); +/// final XFile file = XFile.fromUri(Uri.file('/my/file.txt')); /// /// final IOXFileExtension? ioExtension = file.maybeGetExtension(); /// if (ioExtension != null) { @@ -51,7 +51,7 @@ class XFile extends XFileEntity { /// the dart:io implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformXFileCreationParams(uri: 'my/file.txt'); + /// var params = const PlatformXFileCreationParams(uri: 'file:///my/file.txt'); /// /// if (CrossFilePlatform.instance is CrossFileIO) { /// params = IOXFileCreationParams.fromCreationParams( diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 2eb2fe2785f4..d006088279db 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -47,7 +47,7 @@ class ScopedStorageXFile extends XFile { /// the Android implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformXFileCreationParams(uri: 'my/file.txt'); + /// var params = const PlatformXFileCreationParams(uri: 'file:///my/file.txt'); /// /// if (CrossFilePlatform.instance is CrossFileAndroid) { /// params = AndroidScopedStorageXFileCreationParams.fromCreationParams( From 54177e3f83b17a0293d7644c1b518d8b4e94a066 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:21:32 -0500 Subject: [PATCH 167/398] update cross_file --- packages/cross_file/cross_file/README.md | 8 ++++---- .../cross_file/example/lib/readme_excerpts.dart | 2 +- packages/cross_file/cross_file/example/pubspec.yaml | 9 +++++++++ packages/cross_file/cross_file_web/example/pubspec.yaml | 2 +- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index 0066b1a90fe1..ea831c3c96d7 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -12,11 +12,11 @@ Example: ```dart -final file = XFile('assets/hello.txt'); +final file = XFile.fromUri(Uri.file('assets/hello.txt')); -print('File information:'); -print('- URI: ${file.uri}'); -print('- Name: ${await file.name()}'); +debugPrint('File information:'); +debugPrint('- URI: ${file.uri}'); +debugPrint('- Name: ${await file.name()}'); if (await file.canRead()) { final String fileContent = await file.readAsString(); diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 1ec003a48995..f529b84b0293 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -8,7 +8,7 @@ import 'package:flutter/foundation.dart' show debugPrint; /// Demonstrate instantiating an XFile for the README. Future instantiateXFile() async { // #docregion Instantiate - final file = XFile('assets/hello.txt'); + final file = XFile.fromUri(Uri.file('assets/hello.txt')); debugPrint('File information:'); debugPrint('- URI: ${file.uri}'); diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index 372b96c87841..ce66d0f1832c 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -39,3 +39,12 @@ flutter: uses-material-design: true assets: - assets/hello.txt + +dependency_overrides: + cross_file: + # When depending on this package from a real application you should use: + # cross_file: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ \ No newline at end of file diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index bde81c0eafd7..a88c55a7a699 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -25,7 +25,7 @@ dev_dependencies: dependency_overrides: cross_file_web: # When depending on this package from a real application you should use: - # cross_file_darwin: ^x.y.z + # cross_file_web: ^x.y.z # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. From d2b4422e527607555cda84fbf5819caf83598130 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 14:49:01 -0500 Subject: [PATCH 168/398] ios and macos run --- .../ios/Runner.xcodeproj/project.pbxproj | 112 ++++++++++++++++++ .../contents.xcworkspacedata | 3 + .../macos/Runner.xcodeproj/project.pbxproj | 98 ++++++++++++++- .../contents.xcworkspacedata | 3 + .../macos/Runner/DebugProfile.entitlements | 2 + .../example/macos/Runner/Release.entitlements | 2 + .../cross_file/example/pubspec.yaml | 1 - 7 files changed, 219 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj index ab8983ea48c7..df506fc97283 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 9D5ABF2BFD3F5F3216E37BDF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */; }; + C7741C8FE1202DC4D2942D67 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F576F2A577117482CBAA056 /* Pods_RunnerTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -46,6 +48,10 @@ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 4F576F2A577117482CBAA056 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 725B8D3BB6CDC5144FD4E5B7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -57,6 +63,10 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A008FDEFE186795A9B02CB4F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + A5578CFEE2C8B362F29ECF39 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + DB861370BF100AD4A286A356 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -64,6 +74,15 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9D5ABF2BFD3F5F3216E37BDF /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + E42B53E4B6191CE70EE6A051 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C7741C8FE1202DC4D2942D67 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -96,6 +115,8 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, + C6869AEB60FAA8D6CEE6FA87 /* Pods */, + 9F5AF9B51C64E38CA0A7E19F /* Frameworks */, ); sourceTree = ""; }; @@ -124,6 +145,29 @@ path = Runner; sourceTree = ""; }; + 9F5AF9B51C64E38CA0A7E19F /* Frameworks */ = { + isa = PBXGroup; + children = ( + 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */, + 4F576F2A577117482CBAA056 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + C6869AEB60FAA8D6CEE6FA87 /* Pods */ = { + isa = PBXGroup; + children = ( + 725B8D3BB6CDC5144FD4E5B7 /* Pods-Runner.debug.xcconfig */, + A008FDEFE186795A9B02CB4F /* Pods-Runner.release.xcconfig */, + A5578CFEE2C8B362F29ECF39 /* Pods-Runner.profile.xcconfig */, + DB861370BF100AD4A286A356 /* Pods-RunnerTests.debug.xcconfig */, + 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */, + FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -131,8 +175,10 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + 7D383C8584CA0BAB73229DC3 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, + E42B53E4B6191CE70EE6A051 /* Frameworks */, ); buildRules = ( ); @@ -148,12 +194,14 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 81428E1333C25AFC5945A7F4 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + 9050369081B08E0B437C3785 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -241,6 +289,67 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; + 7D383C8584CA0BAB73229DC3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 81428E1333C25AFC5945A7F4 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9050369081B08E0B437C3785 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -383,6 +492,7 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DB861370BF100AD4A286A356 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -400,6 +510,7 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -415,6 +526,7 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/cross_file/cross_file/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj index d338721e57bf..89936ae96ac4 100644 --- a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,12 +21,14 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 223056F6078A0B29F9794331 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13AF930B762038462526C125 /* Pods_RunnerTests.framework */; }; 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + CDCABB3C5E47BFDA2D2D1F97 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD409983E262F02D75B6545E /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -60,11 +62,13 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 13AF930B762038462526C125 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 1791B30977A096C697D5C0C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; - 33CC10ED2044A3C60003C045 /* cross_file_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "cross_file_example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10ED2044A3C60003C045 /* cross_file_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cross_file_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; @@ -76,8 +80,14 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 437F33A43BFDC4B887DE8BDA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 51890A064A97BBBEC5098087 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; + A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + B63E82A3F401053BCA32C3C4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + FD409983E262F02D75B6545E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,6 +95,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 223056F6078A0B29F9794331 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -92,6 +103,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + CDCABB3C5E47BFDA2D2D1F97 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,6 +137,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, + 3DE641040F107AF7D132DC0F /* Pods */, ); sourceTree = ""; }; @@ -172,9 +185,25 @@ path = Runner; sourceTree = ""; }; + 3DE641040F107AF7D132DC0F /* Pods */ = { + isa = PBXGroup; + children = ( + B63E82A3F401053BCA32C3C4 /* Pods-Runner.debug.xcconfig */, + 51890A064A97BBBEC5098087 /* Pods-Runner.release.xcconfig */, + 1791B30977A096C697D5C0C4 /* Pods-Runner.profile.xcconfig */, + 437F33A43BFDC4B887DE8BDA /* Pods-RunnerTests.debug.xcconfig */, + A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */, + AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( + FD409983E262F02D75B6545E /* Pods_Runner.framework */, + 13AF930B762038462526C125 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -186,6 +215,7 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( + C46F10307CFD10DE28500907 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -204,11 +234,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( + 254EC0B0D434ADEDBB256DFD /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, + 83C208260E55B8C426E85FC5 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -291,6 +323,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 254EC0B0D434ADEDBB256DFD /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -329,6 +383,45 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; + 83C208260E55B8C426E85FC5 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C46F10307CFD10DE28500907 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -380,6 +473,7 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 437F33A43BFDC4B887DE8BDA /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -394,6 +488,7 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -408,6 +503,7 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; + baseConfigurationReference = AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata b/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata index 1d526a16ed0f..21a3cc14c74e 100644 --- a/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata +++ b/packages/cross_file/cross_file/example/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -4,4 +4,7 @@ + + diff --git a/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements b/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements index dddb8a30c851..68acb49b6928 100644 --- a/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements +++ b/packages/cross_file/cross_file/example/macos/Runner/DebugProfile.entitlements @@ -8,5 +8,7 @@ com.apple.security.network.server + com.apple.security.files.user-selected.read-write + diff --git a/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements b/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements index 852fa1a4728a..012d091fca66 100644 --- a/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements +++ b/packages/cross_file/cross_file/example/macos/Runner/Release.entitlements @@ -4,5 +4,7 @@ com.apple.security.app-sandbox + com.apple.security.files.user-selected.read-write + diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index ce66d0f1832c..74f00c5772f9 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -27,7 +27,6 @@ dependencies: flutter_driver: sdk: flutter mime: ^2.0.0 - video_player: ^2.8.6 dev_dependencies: flutter_test: From 87d2fe463c4cb25dcdec8cac8cf22da52f740c7a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:07:19 -0500 Subject: [PATCH 169/398] remove print --- packages/cross_file/cross_file_web/example/lib/main.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index cadb2349f373..4ffd44234094 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -17,7 +17,6 @@ class FileOpenScreen extends StatelessWidget { Future _openFile(BuildContext context) async { final XFile? file = await openFile(); - print('here: ${file?.uri}'); if (file != null) { final String filename = await file.name() ?? file.uri; From 3b52614b82ae12d5dd9648f8dab16b0f3b2a6ca4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:18:58 -0500 Subject: [PATCH 170/398] fix darwin unit tests --- .../test/darwin_cross_directory_test.dart | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart index 2e36fe66c84c..383c9d6df07f 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_cross_directory_test.dart @@ -13,9 +13,10 @@ import 'darwin_cross_directory_test.mocks.dart'; @GenerateMocks([CrossFileDarwinApi]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); + test('startAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; + const uri = 'uri/'; const result = true; when( mockApi.startAccessingSecurityScopedResource(uri), @@ -30,7 +31,7 @@ void main() { test('stopAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; + const uri = 'uri/'; final file = DarwinXDirectory( DarwinXDirectoryCreationParams(uri: uri, api: mockApi), @@ -42,8 +43,8 @@ void main() { test('tryCreateBookmarkedUrl', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const bookmarkedUri = 'newUri'; + const uri = 'uri/'; + const bookmarkedUri = 'newUri/'; when( mockApi.tryCreateBookmarkedUrl(uri), ).thenAnswer((_) async => bookmarkedUri); From 7df932b99b94dbad087c960bc978e5fb8c6dccca Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:33:03 -0500 Subject: [PATCH 171/398] fix test running code --- packages/cross_file/cross_file_web/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md index b360059af5be..a5063b9a37aa 100644 --- a/packages/cross_file/cross_file_web/README.md +++ b/packages/cross_file/cross_file_web/README.md @@ -30,7 +30,7 @@ its size is known beforehand), so that case can be handled programmatically. ### Tests -Tests for the web platform can be run with `dart test -p chrome`. +Tests for the web platform can be run with `flutter test -d chrome`. [1]: https://pub.dev/packages/cross_file [2]: https://flutter.dev/to/endorsed-federated-plugin From 7f900659db58bbdd765f547816111539428e638e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:51:32 -0500 Subject: [PATCH 172/398] remove old cross file --- packages/cross_file/lib/src/types/html.dart | 195 ------------------ .../lib/src/web_helpers/web_helpers.dart | 70 ------- packages/cross_file/pubspec.yaml | 19 -- .../cross_file/test/x_file_html_test.dart | 173 ---------------- 4 files changed, 457 deletions(-) delete mode 100644 packages/cross_file/lib/src/types/html.dart delete mode 100644 packages/cross_file/lib/src/web_helpers/web_helpers.dart delete mode 100644 packages/cross_file/pubspec.yaml delete mode 100644 packages/cross_file/test/x_file_html_test.dart diff --git a/packages/cross_file/lib/src/types/html.dart b/packages/cross_file/lib/src/types/html.dart deleted file mode 100644 index 40703aa754fc..000000000000 --- a/packages/cross_file/lib/src/types/html.dart +++ /dev/null @@ -1,195 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:async'; -import 'dart:convert'; -import 'dart:js_interop'; -import 'dart:typed_data'; - -import 'package:web/web.dart'; - -import '../web_helpers/web_helpers.dart'; -import 'base.dart'; - -// Four Gigabytes, in bytes. -const int _fourGigabytes = 4 * 1024 * 1024 * 1024; - -/// A CrossFile that works on web. -/// -/// It wraps the bytes of a selected file. -class XFile extends XFileBase { - /// Construct a CrossFile object from its ObjectUrl. - /// - /// Optionally, this can be initialized with `bytes` and `length` - /// so no http requests are performed to retrieve files later. - /// - /// `name` needs to be passed from the outside, since it's only available - /// while handling [html.File]s (when the ObjectUrl is created). - // ignore: use_super_parameters - XFile( - String path, { - String? mimeType, - String? name, - int? length, - Uint8List? bytes, - DateTime? lastModified, - }) : _mimeType = mimeType, - _path = path, - _length = length, - _lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0), - _name = name ?? '', - super(path) { - // Cache `bytes` as Blob, if passed. - if (bytes != null) { - _browserBlob = _createBlobFromBytes(bytes, mimeType); - } - } - - /// Construct an CrossFile from its data - XFile.fromData( - Uint8List bytes, { - String? mimeType, - String? name, - int? length, - DateTime? lastModified, - String? path, - }) : _mimeType = mimeType, - _length = length, - _lastModified = lastModified ?? DateTime.fromMillisecondsSinceEpoch(0), - _name = name ?? '', - super(path) { - _browserBlob = _createBlobFromBytes(bytes, mimeType); - _path = URL.createObjectURL(_browserBlob!); - } - - // Initializes a Blob from a bunch of `bytes` and an optional `mimeType`. - Blob _createBlobFromBytes(Uint8List bytes, String? mimeType) { - return (mimeType == null) - ? Blob([bytes.toJS].toJS) - : Blob( - [bytes.toJS].toJS, - BlobPropertyBag(type: mimeType), - ); - } - - // Overridable (meta) data that can be specified by the constructors. - - // MimeType of the file (eg: "image/gif"). - final String? _mimeType; - - // Name (with extension) of the file (eg: "anim.gif") - final String _name; - - // Path of the file (must be a valid Blob URL, when set manually!) - late String _path; - - // The size of the file (in bytes). - final int? _length; - - // The time the file was last modified. - final DateTime _lastModified; - - // The link to the binary object in the browser memory (Blob). - // This can be passed in (as `bytes` in the constructor) or derived from - // [_path] with a fetch request. - // (Similar to a (read-only) dart:io File.) - Blob? _browserBlob; - - @override - String? get mimeType => _mimeType; - - @override - String get name => _name; - - @override - String get path => _path; - - @override - Future lastModified() async => _lastModified; - - Future get _blob async { - if (_browserBlob != null) { - return _browserBlob!; - } - - // Attempt to re-hydrate the blob from the `path` via a (local) HttpRequest. - // Note that safari hangs if the Blob is >=4GB, so bail out in that case. - if (isSafari() && _length != null && _length >= _fourGigabytes) { - throw Exception('Safari cannot handle XFiles larger than 4GB.'); - } - - final blobCompleter = Completer(); - - late XMLHttpRequest request; - request = XMLHttpRequest() - ..open('get', path, true) - ..responseType = 'blob' - ..onLoad.listen((ProgressEvent e) { - assert( - request.response != null, - 'The Blob backing this XFile cannot be null!', - ); - blobCompleter.complete(request.response! as Blob); - }) - ..onError.listen((ProgressEvent e) { - if (e.type == 'error') { - blobCompleter.completeError( - Exception('Could not load Blob from its URL. Has it been revoked?'), - ); - } - }) - ..send(); - - return blobCompleter.future; - } - - @override - Future readAsBytes() async { - return _blob.then(_blobToByteBuffer); - } - - @override - Future length() async => _length ?? (await _blob).size; - - @override - Future readAsString({Encoding encoding = utf8}) async { - return readAsBytes().then(encoding.decode); - } - - // TODO(dit): https://github.com/flutter/flutter/issues/91867 Implement openRead properly. - @override - Stream openRead([int? start, int? end]) async* { - final Blob blob = await _blob; - - final Blob slice = blob.slice(start ?? 0, end ?? blob.size, blob.type); - - final Uint8List convertedSlice = await _blobToByteBuffer(slice); - - yield convertedSlice; - } - - // Converts an html Blob object to a Uint8List, through a FileReader. - Future _blobToByteBuffer(Blob blob) async { - final reader = FileReader(); - reader.readAsArrayBuffer(blob); - - await reader.onLoadEnd.first; - - final Uint8List? result = (reader.result as JSArrayBuffer?)?.toDart - .asUint8List(); - - if (result == null) { - throw Exception('Cannot read bytes from Blob. Is it still available?'); - } - - return result; - } - - /// Saves the data of this CrossFile at the location indicated by path. - /// For the web implementation, the path variable is ignored. - @override - Future saveTo(String path) async { - await saveFileAs(this); - } -} diff --git a/packages/cross_file/lib/src/web_helpers/web_helpers.dart b/packages/cross_file/lib/src/web_helpers/web_helpers.dart deleted file mode 100644 index 58231dd8c30e..000000000000 --- a/packages/cross_file/lib/src/web_helpers/web_helpers.dart +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:meta/meta.dart'; -import 'package:web/web.dart'; - -import '../types/html.dart'; - -/// Type definition for function that creates anchor elements -typedef CreateAnchorElement = - HTMLAnchorElement Function(String href, String? suggestedName); - -/// Create anchor element with download attribute -HTMLAnchorElement _createAnchorElementImpl( - String href, - String? suggestedName, -) => (document.createElement('a') as HTMLAnchorElement) - ..href = href - ..download = suggestedName ?? 'download'; - -/// Function for creating anchor elements. Can be overridden for testing. -@visibleForTesting -CreateAnchorElement createAnchorElementFunction = _createAnchorElementImpl; - -/// Add an element to a container and click it -void addElementToContainerAndClick(Element container, HTMLElement element) { - // Add the element and click it - // All previous elements will be removed before adding the new one - container.appendChild(element); - element.click(); -} - -/// Initializes a DOM container where elements can be injected. -Element ensureInitialized(String id) { - Element? target = document.querySelector('#$id'); - if (target == null) { - final Element targetElement = document.createElement('flt-x-file')..id = id; - - document.body!.appendChild(targetElement); - target = targetElement; - } - return target; -} - -/// Determines if the browser is Safari from its vendor string. -/// (This is the same check used in flutter/engine) -bool isSafari() { - return window.navigator.vendor == 'Apple Computer, Inc.'; -} - -/// Saves the given [XFile] to user's device ("Save As" dialog). -Future saveFileAs(XFile file) async { - // Create container element. - final Element target = ensureInitialized('__x_file_dom_element'); - - // Create element. - final HTMLAnchorElement element = createAnchorElementFunction( - file.path, - file.name, - ); - - // Clear existing children before appending new one. - while (target.children.length > 0) { - target.removeChild(target.children.item(0)!); - } - - // Add and click. - addElementToContainerAndClick(target, element); -} diff --git a/packages/cross_file/pubspec.yaml b/packages/cross_file/pubspec.yaml deleted file mode 100644 index dedcc19f8ae5..000000000000 --- a/packages/cross_file/pubspec.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: cross_file -description: An abstraction to allow working with files across multiple platforms. -repository: https://github.com/flutter/packages/tree/main/packages/cross_file -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.3.5+2 - -environment: - sdk: ^3.8.0 - -dependencies: - meta: ^1.3.0 - web: ">=0.5.1 <2.0.0" - -dev_dependencies: - path: ^1.8.1 - test: ^1.21.1 - -topics: - - files diff --git a/packages/cross_file/test/x_file_html_test.dart b/packages/cross_file/test/x_file_html_test.dart deleted file mode 100644 index e57e36c285c7..000000000000 --- a/packages/cross_file/test/x_file_html_test.dart +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@TestOn('chrome') // Uses web-only Flutter SDK -library; - -import 'dart:convert'; -import 'dart:js_interop'; -import 'dart:typed_data'; - -import 'package:cross_file/cross_file.dart'; -import 'package:cross_file/src/web_helpers/web_helpers.dart' as helpers; -import 'package:test/test.dart'; -import 'package:web/web.dart' as html; - -const String expectedStringContents = 'Hello, world! I ❤ ñ! 空手'; -final Uint8List bytes = Uint8List.fromList(utf8.encode(expectedStringContents)); -final html.File textFile = html.File( - [bytes.toJS].toJS, - 'hello.txt', -); -final String textFileUrl = - // TODO(kevmoo): drop ignore when pkg:web constraint excludes v0.3 - // ignore: unnecessary_cast - html.URL.createObjectURL(textFile as JSObject); - -void main() { - group('Create with an objectUrl', () { - final file = XFile(textFileUrl); - - test('Can be read as a string', () async { - expect(await file.readAsString(), equals(expectedStringContents)); - }); - - test('Can be read as bytes', () async { - expect(await file.readAsBytes(), equals(bytes)); - }); - - test('Can be read as a stream', () async { - expect(await file.openRead().first, equals(bytes)); - }); - - test('Stream can be sliced', () async { - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - }); - - group('Create from data', () { - final file = XFile.fromData(bytes); - - test('Can be read as a string', () async { - expect(await file.readAsString(), equals(expectedStringContents)); - }); - - test('Can be read as bytes', () async { - expect(await file.readAsBytes(), equals(bytes)); - }); - - test('Can be read as a stream', () async { - expect(await file.openRead().first, equals(bytes)); - }); - - test('Stream can be sliced', () async { - expect(await file.openRead(2, 5).first, equals(bytes.sublist(2, 5))); - }); - - test('Prefers local bytes over path if both are provided', () async { - const text = 'Hello World'; - const path = 'test/x_file_html_test.dart'; - - final file = XFile.fromData( - utf8.encode(text), - path: path, - name: 'x_file_html_test.dart', - length: text.length, - mimeType: 'text/plain', - lastModified: DateTime.now(), - ); - - expect(file.path, isNot(equals(path))); - expect(file.path.startsWith('blob:'), isTrue); - expect(await file.readAsString(), equals(text)); - }); - }); - - group('Blob backend', () { - final file = XFile(textFileUrl); - - test('Stores data as a Blob', () async { - // Read the blob from its path 'natively' - final html.Response response = await html.window - .fetch(file.path.toJS) - .toDart; - - final JSAny arrayBuffer = await response.arrayBuffer().toDart; - final ByteBuffer data = (arrayBuffer as JSArrayBuffer).toDart; - expect(data.asUint8List(), equals(bytes)); - }); - - test('Data may be purged from the blob!', () async { - html.URL.revokeObjectURL(file.path); - - expect(() async { - await file.readAsBytes(); - }, throwsException); - }); - }); - - group('saveTo(..)', () { - const crossFileDomElementId = '__x_file_dom_element'; - - group('CrossFile saveTo(..)', () { - test('creates a DOM container', () async { - final file = XFile.fromData(bytes); - - await file.saveTo(''); - - final html.Element? container = html.document.querySelector( - '#$crossFileDomElementId', - ); - - expect(container, isNotNull); - }); - - test('create anchor element', () async { - final file = XFile.fromData(bytes, name: textFile.name); - - await file.saveTo('path'); - - final html.Element container = html.document.querySelector( - '#$crossFileDomElementId', - )!; - - late html.HTMLAnchorElement element; - for (var i = 0; i < container.childNodes.length; i++) { - final html.Element test = container.children.item(i)!; - if (test.tagName == 'A') { - element = test as html.HTMLAnchorElement; - break; - } - } - - // if element is not found, the `firstWhere` call will throw StateError. - expect(element.href, file.path); - expect(element.download, file.name); - }); - - test('anchor element is clicked', () async { - final mockAnchor = - html.document.createElement('a') as html.HTMLAnchorElement; - - // Save original function so we can restore it - final helpers.CreateAnchorElement original = - helpers.createAnchorElementFunction; - - addTearDown(() { - helpers.createAnchorElementFunction = original; - }); - helpers.createAnchorElementFunction = (_, __) => mockAnchor; - - final file = XFile.fromData(bytes, name: textFile.name); - - var clicked = false; - mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); - - await file.saveTo('path'); - - expect(clicked, true); - }); - }); - }); -} From 569cf177de3223c8e180ce6aba68185ba4baa6a5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 15:57:56 -0500 Subject: [PATCH 173/398] format swift code --- .../Tests/CrossFileDarwinApiTests.swift | 32 ++++++++--------- .../darwin/cross_file_darwin/Package.swift | 36 +++++++++---------- .../CrossFileDarwinApis.g.swift | 24 +++++++++---- .../CrossFileDarwinApiImpl.swift | 10 +++--- .../example/ios/RunnerTests/RunnerTests.swift | 10 +++--- .../lib/cross_file_darwin.dart | 6 ++-- .../lib/src/cross_file_darwin_apis.g.dart | 32 +++++++++++------ 7 files changed, 88 insertions(+), 62 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 300e79a710db..2cf1040bffdc 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -2,6 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Testing + +@testable import cross_file_darwin + #if os(iOS) import Flutter #elseif os(macOS) @@ -10,42 +14,38 @@ #error("Unsupported platform.") #endif -import Testing - -@testable import cross_file_darwin - struct CrossFileDarwinApiTests { func createTempTestFile() throws -> URL { let fileManager = FileManager.default let tempDirectory = fileManager.temporaryDirectory let fileName = UUID().uuidString + ".txt" let fileURL = tempDirectory.appendingPathComponent(fileName) - + try "Hello, World!".write(to: fileURL, atomically: true, encoding: .utf8) - + return fileURL } - + @Test func startAccessingSecurityScopedResource() throws { let testFileURL = try createTempTestFile() - + let api = CrossFileDarwinApiImpl() let canAccess = try api.startAccessingSecurityScopedResource(url: testFileURL.absoluteString) - + // Only returns true on iOS. -#if os(iOS) - #expect(canAccess) -#endif - + #if os(iOS) + #expect(canAccess) + #endif + #expect(try String(contentsOf: testFileURL, encoding: .utf8) == "Hello, World!") } - + @Test func tryCreateBookmarkedUrl() throws { let testFileURL = try createTempTestFile() - + let api = CrossFileDarwinApiImpl() let bookmarkedURLString = try! api.tryCreateBookmarkedUrl(url: testFileURL.absoluteString)! - + #expect(URL(fileURLWithPath: bookmarkedURLString) == testFileURL) } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift index c3658d759b2c..977be8ef52db 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift @@ -7,22 +7,22 @@ import PackageDescription let package = Package( - name: "cross_file_darwin", - platforms: [ - .iOS("13.0"), - .macOS("10.15"), - ], - products: [ - .library(name: "cross-file-darwin", targets: ["cross_file_darwin"]) - ], - dependencies: [], - targets: [ - .target( - name: "cross_file_darwin", - dependencies: [], - resources: [ - .process("Resources") - ] - ) - ] + name: "cross_file_darwin", + platforms: [ + .iOS("13.0"), + .macOS("10.15"), + ], + products: [ + .library(name: "cross-file-darwin", targets: ["cross_file_darwin"]) + ], + dependencies: [], + targets: [ + .target( + name: "cross_file_darwin", + dependencies: [], + resources: [ + .process("Resources") + ] + ) + ] ) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index a3d3a6406986..6718f7f13329 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -67,7 +67,6 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } - private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { } @@ -85,7 +84,8 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Api for getting access to file information. @@ -107,11 +107,17 @@ protocol CrossFileDarwinApi { class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -128,7 +134,10 @@ class CrossFileDarwinApiSetup { } /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -145,7 +154,10 @@ class CrossFileDarwinApiSetup { } /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index d856fef30b83..391fca70b47c 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Foundation + #if os(iOS) -import Flutter + import Flutter #elseif os(macOS) -import FlutterMacOS + import FlutterMacOS #else -#error("Unsupported platform.") + #error("Unsupported platform.") #endif -import Foundation - /// Implementation of `CrossFileDarwinApi`. class CrossFileDarwinApiImpl: CrossFileDarwinApi { func tryCreateBookmarkedUrl(url: String) throws -> String? { diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift index 3c40eba6e449..1e018c094ec5 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import Testing +import UIKit + +@testable import cross_file_darwin + #if os(iOS) import Flutter #elseif os(macOS) @@ -10,11 +15,6 @@ #error("Unsupported platform.") #endif -import Testing -import UIKit - -@testable import cross_file_darwin - struct RunnerTests { @Test func testGetPlatform() { #expect(true == true) diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index fb305b8803c0..f24d11da676f 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -6,6 +6,8 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXFileEntity; export 'src/cross_file_darwin.dart'; -export 'src/darwin_cross_directory.dart' show DarwinXDirectoryCreationParams, DarwinXDirectoryExtension; -export 'src/darwin_cross_file.dart' show DarwinXFileCreationParams, DarwinXFileExtension; +export 'src/darwin_cross_directory.dart' + show DarwinXDirectoryCreationParams, DarwinXDirectoryExtension; +export 'src/darwin_cross_file.dart' + show DarwinXFileCreationParams, DarwinXFileExtension; export 'src/security_scoped_resource.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index f6190d27017a..591a0daa863c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -18,7 +18,6 @@ PlatformException _createConnectionError(String channelName) { ); } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -45,9 +44,13 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + CrossFileDarwinApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -57,13 +60,16 @@ class CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -81,13 +87,16 @@ class CrossFileDarwinApi { /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. Future startAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -110,13 +119,16 @@ class CrossFileDarwinApi { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. Future stopAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); From d9095fb653da93a8e0966eb238b2458aa7eeb458 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:18:01 -0500 Subject: [PATCH 174/398] fix docs --- .../cross_file/lib/src/scoped_storage_cross_directory.dart | 4 ++-- .../cross_file/lib/src/scoped_storage_cross_file.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index daf69b5327ef..5fb2c59e14bb 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -21,7 +21,7 @@ import 'cross_directory.dart'; /// the Android implementation of `cross_file`: /// /// ```dart -/// final ScopedStorageXDirectory directory = ScopedStorageXDirectory(uri: 'context://my/dir'); +/// final ScopedStorageXDirectory directory = ScopedStorageXDirectory(uri: 'content://my/dir'); /// /// final AndroidScopedStorageXDirectoryExtension? androidExtension = /// file.maybeGetExtension(); @@ -48,7 +48,7 @@ class ScopedStorageXDirectory extends XDirectory { /// the Android implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformXDirectoryCreationParams(uri: 'context://my/docs'); + /// var params = const PlatformScopedStorageXDirectoryCreationParams(uri: 'content://my/docs'); /// /// if (CrossFilePlatform.instance is CrossFileAndroid) { /// params = AndroidScopedStorageXDirectoryCreationParams.fromCreationParams( diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index d006088279db..f14a3bf3f95c 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -20,7 +20,7 @@ import 'cross_file.dart'; /// the Android implementation of `cross_file`: /// /// ```dart -/// final ScopedStorageXFile file = ScopedStorageXFile(uri: 'context://my/file.txt'); +/// final ScopedStorageXFile file = ScopedStorageXFile(uri: 'content://my/file.txt'); /// /// final AndroidScopedStorageXFileExtension? androidExtension = /// file.maybeGetExtension(); @@ -47,7 +47,7 @@ class ScopedStorageXFile extends XFile { /// the Android implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformXFileCreationParams(uri: 'file:///my/file.txt'); + /// var params = const PlatformScopedStorageXFileCreationParams(uri: 'content://my/file.txt'); /// /// if (CrossFilePlatform.instance is CrossFileAndroid) { /// params = AndroidScopedStorageXFileCreationParams.fromCreationParams( From 831561bcca7a280e1e618f8cb47077dffc58e9c0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:21:46 -0500 Subject: [PATCH 175/398] format linux code --- .../example/linux/runner/my_application.h | 5 +- .../example/windows/runner/flutter_window.cpp | 4 +- .../example/windows/runner/main.cpp | 5 +- .../example/windows/runner/resource.h | 10 +- .../example/windows/runner/utils.cpp | 14 +- .../example/windows/runner/win32_window.cpp | 38 +- .../example/windows/runner/win32_window.h | 6 +- .../proxies/AndroidLibrary.g.kt | 625 ++++++++++-------- .../lib/src/android_library.g.dart | 360 ++++++---- 9 files changed, 614 insertions(+), 453 deletions(-) diff --git a/packages/cross_file/cross_file/example/linux/runner/my_application.h b/packages/cross_file/cross_file/example/linux/runner/my_application.h index db16367a77d0..72271d5e4170 100644 --- a/packages/cross_file/cross_file/example/linux/runner/my_application.h +++ b/packages/cross_file/cross_file/example/linux/runner/my_application.h @@ -3,10 +3,7 @@ #include -G_DECLARE_FINAL_TYPE(MyApplication, - my_application, - MY, - APPLICATION, +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, GtkApplication) /** diff --git a/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp b/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp index 955ee3038f98..bd97f8937881 100644 --- a/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp +++ b/packages/cross_file/cross_file/example/windows/runner/flutter_window.cpp @@ -27,9 +27,7 @@ bool FlutterWindow::OnCreate() { RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); - flutter_controller_->engine()->SetNextFrameCallback([&]() { - this->Show(); - }); + flutter_controller_->engine()->SetNextFrameCallback([&]() { this->Show(); }); // Flutter can complete the first frame before the "show window" callback is // registered. The following call ensures a frame is pending to ensure the diff --git a/packages/cross_file/cross_file/example/windows/runner/main.cpp b/packages/cross_file/cross_file/example/windows/runner/main.cpp index 24c271d29c8f..e8087fae3ad5 100644 --- a/packages/cross_file/cross_file/example/windows/runner/main.cpp +++ b/packages/cross_file/cross_file/example/windows/runner/main.cpp @@ -6,7 +6,7 @@ #include "utils.h" int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, - _In_ wchar_t *command_line, _In_ int show_command) { + _In_ wchar_t* command_line, _In_ int show_command) { // Attach to console when present (e.g., 'flutter run') or create a // new console when running with a debugger. if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { @@ -19,8 +19,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, flutter::DartProject project(L"data"); - std::vector command_line_arguments = - GetCommandLineArguments(); + std::vector command_line_arguments = GetCommandLineArguments(); project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); diff --git a/packages/cross_file/cross_file/example/windows/runner/resource.h b/packages/cross_file/cross_file/example/windows/runner/resource.h index 66a65d1e4a79..d5d958dc4257 100644 --- a/packages/cross_file/cross_file/example/windows/runner/resource.h +++ b/packages/cross_file/cross_file/example/windows/runner/resource.h @@ -2,15 +2,15 @@ // Microsoft Visual C++ generated include file. // Used by Runner.rc // -#define IDI_APP_ICON 101 +#define IDI_APP_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/packages/cross_file/cross_file/example/windows/runner/utils.cpp b/packages/cross_file/cross_file/example/windows/runner/utils.cpp index 3a0b46511a71..cf06cfe8c9cf 100644 --- a/packages/cross_file/cross_file/example/windows/runner/utils.cpp +++ b/packages/cross_file/cross_file/example/windows/runner/utils.cpp @@ -9,7 +9,7 @@ void CreateAndAttachConsole() { if (::AllocConsole()) { - FILE *unused; + FILE* unused; if (freopen_s(&unused, "CONOUT$", "w", stdout)) { _dup2(_fileno(stdout), 1); } @@ -45,10 +45,10 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { if (utf16_string == nullptr) { return std::string(); } - unsigned int target_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - -1, nullptr, 0, nullptr, nullptr) - -1; // remove the trailing null character + unsigned int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr) - + 1; // remove the trailing null character int input_length = (int)wcslen(utf16_string); std::string utf8_string; if (target_length == 0 || target_length > utf8_string.max_size()) { @@ -56,8 +56,8 @@ std::string Utf8FromUtf16(const wchar_t* utf16_string) { } utf8_string.resize(target_length); int converted_length = ::WideCharToMultiByte( - CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, - input_length, utf8_string.data(), target_length, nullptr, nullptr); + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, input_length, + utf8_string.data(), target_length, nullptr, nullptr); if (converted_length == 0) { return std::string(); } diff --git a/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp b/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp index 60608d0fe5bf..78a1036f790e 100644 --- a/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp +++ b/packages/cross_file/cross_file/example/windows/runner/win32_window.cpp @@ -11,7 +11,8 @@ namespace { /// /// Redefined in case the developer's machine has a Windows SDK older than /// version 10.0.22000.0. -/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +/// See: +/// https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute #ifndef DWMWA_USE_IMMERSIVE_DARK_MODE #define DWMWA_USE_IMMERSIVE_DARK_MODE 20 #endif @@ -23,8 +24,9 @@ constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; /// A value of 0 indicates apps should use dark mode. A non-zero or missing /// value indicates apps should use light mode. constexpr const wchar_t kGetPreferredBrightnessRegKey[] = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; -constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = + L"AppsUseLightTheme"; // The number of Win32Window objects that currently exist. static int g_active_window_count = 0; @@ -111,17 +113,14 @@ void WindowClassRegistrar::UnregisterWindowClass() { class_registered_ = false; } -Win32Window::Win32Window() { - ++g_active_window_count; -} +Win32Window::Win32Window() { ++g_active_window_count; } Win32Window::~Win32Window() { --g_active_window_count; Destroy(); } -bool Win32Window::Create(const std::wstring& title, - const Point& origin, +bool Win32Window::Create(const std::wstring& title, const Point& origin, const Size& size) { Destroy(); @@ -149,13 +148,10 @@ bool Win32Window::Create(const std::wstring& title, return OnCreate(); } -bool Win32Window::Show() { - return ShowWindow(window_handle_, SW_SHOWNORMAL); -} +bool Win32Window::Show() { return ShowWindow(window_handle_, SW_SHOWNORMAL); } // static -LRESULT CALLBACK Win32Window::WndProc(HWND const window, - UINT const message, +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { if (message == WM_NCCREATE) { @@ -174,9 +170,7 @@ LRESULT CALLBACK Win32Window::WndProc(HWND const window, } LRESULT -Win32Window::MessageHandler(HWND hwnd, - UINT const message, - WPARAM const wparam, +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { switch (message) { case WM_DESTROY: @@ -255,9 +249,7 @@ RECT Win32Window::GetClientArea() { return frame; } -HWND Win32Window::GetHandle() { - return window_handle_; -} +HWND Win32Window::GetHandle() { return window_handle_; } void Win32Window::SetQuitOnClose(bool quit_on_close) { quit_on_close_ = quit_on_close; @@ -275,10 +267,10 @@ void Win32Window::OnDestroy() { void Win32Window::UpdateTheme(HWND const window) { DWORD light_mode; DWORD light_mode_size = sizeof(light_mode); - LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, - kGetPreferredBrightnessRegValue, - RRF_RT_REG_DWORD, nullptr, &light_mode, - &light_mode_size); + LSTATUS result = + RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, nullptr, + &light_mode, &light_mode_size); if (result == ERROR_SUCCESS) { BOOL enable_dark_mode = light_mode == 0; diff --git a/packages/cross_file/cross_file/example/windows/runner/win32_window.h b/packages/cross_file/cross_file/example/windows/runner/win32_window.h index e901dde684ea..3f9c655139fb 100644 --- a/packages/cross_file/cross_file/example/windows/runner/win32_window.h +++ b/packages/cross_file/cross_file/example/windows/runner/win32_window.h @@ -59,8 +59,7 @@ class Win32Window { // Processes and route salient window messages for mouse handling, // size change and DPI. Delegates handling of these to member overloads that // inheriting classes can handle. - virtual LRESULT MessageHandler(HWND window, - UINT const message, + virtual LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept; @@ -79,8 +78,7 @@ class Win32Window { // non-client DPI scaling so that the non-client area automatically // responds to changes in DPI. All other messages are handled by // MessageHandler. - static LRESULT CALLBACK WndProc(HWND const window, - UINT const message, + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept; diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt index 0c540f90fafe..10b5175cc75e 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt @@ -10,16 +10,17 @@ package dev.flutter.packages.cross_file_android.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel import io.flutter.plugin.common.BinaryMessenger -import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MessageCodec -import io.flutter.plugin.common.StandardMethodCodec import io.flutter.plugin.common.StandardMessageCodec import java.io.ByteArrayOutputStream import java.nio.ByteBuffer + private object AndroidLibraryPigeonUtils { fun createConnectionError(channelName: String): FlutterError { - return FlutterError("channel-error", "Unable to establish connection on channel: '$channelName'.", "") } + return FlutterError( + "channel-error", "Unable to establish connection on channel: '$channelName'.", "") + } fun wrapResult(result: Any?): List { return listOf(result) @@ -27,50 +28,48 @@ private object AndroidLibraryPigeonUtils { fun wrapError(exception: Throwable): List { return if (exception is FlutterError) { - listOf( - exception.code, - exception.message, - exception.details - ) + listOf(exception.code, exception.message, exception.details) } else { listOf( - exception.javaClass.simpleName, - exception.toString(), - "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception) - ) + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) } } } /** * Error class for passing custom error details to Flutter via a thrown PlatformException. + * * @property code The error code. * @property message The error message. * @property details The error details. Must be a datatype supported by the api codec. */ -class FlutterError ( - val code: String, - override val message: String? = null, - val details: Any? = null +class FlutterError( + val code: String, + override val message: String? = null, + val details: Any? = null ) : Throwable() /** * Maintains instances used to communicate with the corresponding objects in Dart. * - * Objects stored in this container are represented by an object in Dart that is also stored in - * an InstanceManager with the same identifier. + * Objects stored in this container are represented by an object in Dart that is also stored in an + * InstanceManager with the same identifier. * * When an instance is added with an identifier, either can be used to retrieve the other. * - * Added instances are added as a weak reference and a strong reference. When the strong - * reference is removed with [remove] and the weak reference is deallocated, the - * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the strong - * reference is removed and then the identifier is retrieved with the intention to pass the identifier - * to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance - * is recreated. The strong reference will then need to be removed manually again. + * Added instances are added as a weak reference and a strong reference. When the strong reference + * is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener.onFinalize` is called with the instance's identifier. However, if the + * strong reference is removed and then the identifier is retrieved with the intention to pass the + * identifier to Dart (e.g. calling [getIdentifierForStrongReference]), the strong reference to the + * instance is recreated. The strong reference will then need to be removed manually again. */ @Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate") -class AndroidLibraryPigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { - /** Interface for listening when a weak reference of an instance is removed from the manager. */ +class AndroidLibraryPigeonInstanceManager( + private val finalizationListener: PigeonFinalizationListener +) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ interface PigeonFinalizationListener { fun onFinalize(identifier: Long) } @@ -139,19 +138,20 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige private const val tag = "PigeonInstanceManager" /** - * Instantiate a new manager with a listener for garbage collected weak - * references. + * Instantiate a new manager with a listener for garbage collected weak references. * * When the manager is no longer needed, [stopFinalizationListener] must be called. */ - fun create(finalizationListener: PigeonFinalizationListener): AndroidLibraryPigeonInstanceManager { + fun create( + finalizationListener: PigeonFinalizationListener + ): AndroidLibraryPigeonInstanceManager { return AndroidLibraryPigeonInstanceManager(finalizationListener) } } /** - * Removes `identifier` and return its associated strongly referenced instance, if present, - * from the manager. + * Removes `identifier` and return its associated strongly referenced instance, if present, from + * the manager. */ fun remove(identifier: Long): T? { logWarningIfFinalizationListenerHasStopped() @@ -161,15 +161,13 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Retrieves the identifier paired with an instance, if present, otherwise `null`. * - * * If the manager contains a strong reference to `instance`, it will return the identifier * associated with `instance`. If the manager contains only a weak reference to `instance`, a new * strong reference to `instance` will be added and will need to be removed again with [remove]. * - * * If this method returns a nonnull identifier, this method also expects the Dart - * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - * identifier is associated with. + * `AndroidLibraryPigeonInstanceManager` to have, or recreate, a weak reference to the Dart + * instance the identifier is associated with. */ fun getIdentifierForStrongReference(instance: Any?): Long? { logWarningIfFinalizationListenerHasStopped() @@ -186,9 +184,9 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Adds a new instance that was instantiated from Dart. * - * The same instance can be added multiple times, but each identifier must be unique. This - * allows two objects that are equivalent (e.g. the `equals` method returns true and their - * hashcodes are equal) to both be added. + * The same instance can be added multiple times, but each identifier must be unique. This allows + * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are + * equal) to both be added. * * [identifier] must be >= 0 and unique. */ @@ -200,13 +198,15 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige /** * Adds a new unique instance that was instantiated from the host platform. * - * If the manager contains [instance], this returns the corresponding identifier. If the - * manager does not contain [instance], this adds the instance and returns a unique - * identifier for that [instance]. + * If the manager contains [instance], this returns the corresponding identifier. If the manager + * does not contain [instance], this adds the instance and returns a unique identifier for that + * [instance]. */ fun addHostCreatedInstance(instance: Any): Long { logWarningIfFinalizationListenerHasStopped() - require(!containsInstance(instance)) { "Instance of ${instance.javaClass} has already been added." } + require(!containsInstance(instance)) { + "Instance of ${instance.javaClass} has already been added." + } val identifier = nextIdentifier++ addInstance(instance, identifier) return identifier @@ -290,39 +290,43 @@ class AndroidLibraryPigeonInstanceManager(private val finalizationListener: Pige private fun logWarningIfFinalizationListenerHasStopped() { if (hasFinalizationListenerStopped()) { Log.w( - tag, - "The manager was used after calls to the PigeonFinalizationListener has been stopped." - ) + tag, + "The manager was used after calls to the PigeonFinalizationListener has been stopped.") } } } - /** Generated API for managing the Dart and native `InstanceManager`s. */ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { companion object { /** The codec used by AndroidLibraryPigeonInstanceManagerApi. */ - val codec: MessageCodec by lazy { - AndroidLibraryPigeonCodec() - } + val codec: MessageCodec by lazy { AndroidLibraryPigeonCodec() } /** * Sets up an instance of `AndroidLibraryPigeonInstanceManagerApi` to handle messages from the * `binaryMessenger`. */ - fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: AndroidLibraryPigeonInstanceManager?) { + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + instanceManager: AndroidLibraryPigeonInstanceManager? + ) { run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference", + codec) if (instanceManager != null) { channel.setMessageHandler { message, reply -> val args = message as List val identifierArg = args[0] as Long - val wrapped: List = try { - instanceManager.remove(identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -330,15 +334,20 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.clear", + codec) if (instanceManager != null) { channel.setMessageHandler { _, reply -> - val wrapped: List = try { - instanceManager.clear() - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -348,9 +357,9 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } - fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) -{ - val channelName = "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference" val channel = BasicMessageChannel(binaryMessenger, channelName, codec) channel.send(listOf(identifierArg)) { if (it is List<*>) { @@ -361,13 +370,13 @@ private class AndroidLibraryPigeonInstanceManagerApi(val binaryMessenger: Binary } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } /** - * Provides implementations for each ProxyApi implementation and provides access to resources - * needed by any implementation. + * Provides implementations for each ProxyApi implementation and provides access to resources needed + * by any implementation. */ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { /** Whether APIs should ignore calling to Dart. */ @@ -384,24 +393,23 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary init { val api = AndroidLibraryPigeonInstanceManagerApi(binaryMessenger) - instanceManager = AndroidLibraryPigeonInstanceManager.create( - object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { - override fun onFinalize(identifier: Long) { - api.removeStrongReference(identifier) { - if (it.isFailure) { - Log.e( - "PigeonProxyApiRegistrar", - "Failed to remove Dart strong reference with identifier: $identifier" - ) - } - } - } - } - ) + instanceManager = + AndroidLibraryPigeonInstanceManager.create( + object : AndroidLibraryPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier") + } + } + } + }) } /** - * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of - * `DocumentFile` to the Dart `InstanceManager`. + * An implementation of [PigeonApiDocumentFile] used to add a new Dart instance of `DocumentFile` + * to the Dart `InstanceManager`. */ abstract fun getPigeonApiDocumentFile(): PigeonApiDocumentFile @@ -412,8 +420,8 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary abstract fun getPigeonApiContentResolver(): PigeonApiContentResolver /** - * An implementation of [PigeonApiInputStream] used to add a new Dart instance of - * `InputStream` to the Dart `InstanceManager`. + * An implementation of [PigeonApiInputStream] used to add a new Dart instance of `InputStream` to + * the Dart `InstanceManager`. */ abstract fun getPigeonApiInputStream(): PigeonApiInputStream @@ -423,6 +431,7 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiContentResolver.setUpMessageHandlers(binaryMessenger, getPigeonApiContentResolver()) PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, getPigeonApiInputStream()) } + fun tearDown() { AndroidLibraryPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) PigeonApiDocumentFile.setUpMessageHandlers(binaryMessenger, null) @@ -430,17 +439,17 @@ abstract class AndroidLibraryPigeonProxyApiRegistrar(val binaryMessenger: Binary PigeonApiInputStream.setUpMessageHandlers(binaryMessenger, null) } } -private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibraryPigeonProxyApiRegistrar) : AndroidLibraryPigeonCodec() { + +private class AndroidLibraryPigeonProxyApiBaseCodec( + val registrar: AndroidLibraryPigeonProxyApiRegistrar +) : AndroidLibraryPigeonCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 128.toByte() -> { val identifier: Long = readValue(buffer) as Long val instance: Any? = registrar.instanceManager.getInstance(identifier) if (instance == null) { - Log.e( - "PigeonProxyApiBaseCodec", - "Failed to find instance with identifier: $identifier" - ) + Log.e("PigeonProxyApiBaseCodec", "Failed to find instance with identifier: $identifier") } return instance } @@ -449,16 +458,27 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar } override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { - if (value is Boolean || value is ByteArray || value is Double || value is DoubleArray || value is FloatArray || value is Int || value is IntArray || value is List<*> || value is Long || value is LongArray || value is Map<*, *> || value is String || value == null) { + if (value is Boolean || + value is ByteArray || + value is Double || + value is DoubleArray || + value is FloatArray || + value is Int || + value is IntArray || + value is List<*> || + value is Long || + value is LongArray || + value is Map<*, *> || + value is String || + value == null) { super.writeValue(stream, value) return } fun logNewInstanceFailure(apiName: String, value: Any, exception: Throwable?) { Log.w( - "PigeonProxyApiBaseCodec", - "Failed to create new Dart proxy instance of $apiName: $value. $exception" - ) + "PigeonProxyApiBaseCodec", + "Failed to create new Dart proxy instance of $apiName: $value. $exception") } if (value is androidx.documentfile.provider.DocumentFile) { @@ -467,15 +487,13 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar logNewInstanceFailure("DocumentFile", value, it.exceptionOrNull()) } } - } - else if (value is android.content.ContentResolver) { + } else if (value is android.content.ContentResolver) { registrar.getPigeonApiContentResolver().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("ContentResolver", value, it.exceptionOrNull()) } } - } - else if (value is java.io.InputStream) { + } else if (value is java.io.InputStream) { registrar.getPigeonApiInputStream().pigeon_newInstance(value) { if (it.isFailure) { logNewInstanceFailure("InputStream", value, it.exceptionOrNull()) @@ -488,34 +506,37 @@ private class AndroidLibraryPigeonProxyApiBaseCodec(val registrar: AndroidLibrar stream.write(128) writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) } - else -> throw IllegalArgumentException("Unsupported value: '$value' of type '${value.javaClass.name}'") + else -> + throw IllegalArgumentException( + "Unsupported value: '$value' of type '${value.javaClass.name}'") } } } + private open class AndroidLibraryPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { - return super.readValueOfType(type, buffer) + return super.readValueOfType(type, buffer) } - override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { super.writeValue(stream, value) } } /** - * Representation of a document backed by either a - * android.provider.DocumentsProvider or a raw file on disk. + * Representation of a document backed by either a android.provider.DocumentsProvider or a raw file + * on disk. * * See https://developer.android.com/reference/androidx/documentfile/provider/DocumentFile. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { +abstract class PigeonApiDocumentFile( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { /** Create a DocumentFile representing the single document at the given Uri. */ abstract fun fromSingleUri(singleUri: String): androidx.documentfile.provider.DocumentFile - /** - * Create a DocumentFile representing the document tree rooted at the given - * Uri. - */ + /** Create a DocumentFile representing the document tree rooted at the given Uri. */ abstract fun fromTreeUri(treeUri: String): androidx.documentfile.provider.DocumentFile /** Indicates whether the current context is allowed to read from this file. */ @@ -528,8 +549,8 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig abstract fun exists(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean /** - * Returns the time when this file was last modified, measured in - * milliseconds since January 1st, 1970, midnight. + * Returns the time when this file was last modified, measured in milliseconds since January 1st, + * 1970, midnight. */ abstract fun lastModified(pigeon_instance: androidx.documentfile.provider.DocumentFile): Long @@ -542,11 +563,10 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig /** Indicates if this file represents a *directory*. */ abstract fun isDirectory(pigeon_instance: androidx.documentfile.provider.DocumentFile): Boolean - /** - * Returns an list of files contained in the directory represented by this - * file. - */ - abstract fun listFiles(pigeon_instance: androidx.documentfile.provider.DocumentFile): List + /** Returns an list of files contained in the directory represented by this file. */ + abstract fun listFiles( + pigeon_instance: androidx.documentfile.provider.DocumentFile + ): List /** A Uri for the underlying document represented by this file. */ abstract fun getUri(pigeon_instance: androidx.documentfile.provider.DocumentFile): String @@ -559,18 +579,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiDocumentFile?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val singleUriArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromSingleUri(singleUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromSingleUri(singleUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -578,18 +604,24 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long val treeUriArg = args[1] as String - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.fromTreeUri(treeUriArg), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.fromTreeUri(treeUriArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -597,16 +629,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.canRead", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.canRead(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.canRead(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -614,16 +651,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.delete", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.delete(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.delete(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -631,16 +671,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.exists", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.exists(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.exists(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -648,16 +691,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.lastModified(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.lastModified(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -665,16 +713,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.length", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.length(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.length(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -682,16 +733,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isFile", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.isFile(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.isFile(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -699,16 +753,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.isDirectory(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.isDirectory(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -716,16 +775,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.listFiles(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.listFiles(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -733,16 +797,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getUri", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.getUri(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getUri(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -750,16 +817,21 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.DocumentFile.getName", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.DocumentFile.getName", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as androidx.documentfile.provider.DocumentFile - val wrapped: List = try { - listOf(api.getName(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.getName(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -771,16 +843,19 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of DocumentFile and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: androidx.documentfile.provider.DocumentFile, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance" @@ -788,17 +863,17 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** * This class provides applications access to the content model. @@ -806,32 +881,40 @@ abstract class PigeonApiDocumentFile(open val pigeonRegistrar: AndroidLibraryPig * See https://developer.android.com/reference/kotlin/android/content/ContentResolver */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * Helper field for accessing the `ContentResolver` from the current Android - * `Context`. - */ +abstract class PigeonApiContentResolver( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + /** Helper field for accessing the `ContentResolver` from the current Android `Context`. */ abstract fun instance(): android.content.ContentResolver /** Open a stream on to the content associated with a content URI. */ - abstract fun openInputStream(pigeon_instance: android.content.ContentResolver, uri: String): java.io.InputStream? + abstract fun openInputStream( + pigeon_instance: android.content.ContentResolver, + uri: String + ): java.io.InputStream? companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiContentResolver?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.instance", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_identifierArg = args[0] as Long - val wrapped: List = try { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.instance(), pigeon_identifierArg) - listOf(null) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.instance(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -839,17 +922,22 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as android.content.ContentResolver val uriArg = args[1] as String - val wrapped: List = try { - listOf(api.openInputStream(pigeon_instanceArg, uriArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.openInputStream(pigeon_instanceArg, uriArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -861,16 +949,19 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of ContentResolver and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: android.content.ContentResolver, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: android.content.ContentResolver, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance" @@ -878,30 +969,28 @@ abstract class PigeonApiContentResolver(open val pigeonRegistrar: AndroidLibrary channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } /** - * This abstract class is the superclass of all classes representing an input - * stream of bytes. + * This abstract class is the superclass of all classes representing an input stream of bytes. * * See https://developer.android.com/reference/java/io/InputStream. */ @Suppress("UNCHECKED_CAST") -abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar) { - /** - * Reads some number of bytes from the input stream and stores them into the - * returns them. - */ +abstract class PigeonApiInputStream( + open val pigeonRegistrar: AndroidLibraryPigeonProxyApiRegistrar +) { + /** Reads some number of bytes from the input stream and stores them into the returns them. */ abstract fun readBytes(pigeon_instance: java.io.InputStream, len: Long): ByteArray /** Reads all remaining bytes from the input stream. */ @@ -915,17 +1004,22 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiInputStream?) { val codec = api?.pigeonRegistrar?.codec ?: AndroidLibraryPigeonCodec() run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val lenArg = args[1] as Long - val wrapped: List = try { - listOf(api.readBytes(pigeon_instanceArg, lenArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readBytes(pigeon_instanceArg, lenArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -933,16 +1027,21 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", codec) + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes", + codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream - val wrapped: List = try { - listOf(api.readAllBytes(pigeon_instanceArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.readAllBytes(pigeon_instanceArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -950,17 +1049,20 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige } } run { - val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) + val channel = + BasicMessageChannel( + binaryMessenger, "dev.flutter.pigeon.cross_file_android.InputStream.skip", codec) if (api != null) { channel.setMessageHandler { message, reply -> val args = message as List val pigeon_instanceArg = args[0] as java.io.InputStream val nArg = args[1] as Long - val wrapped: List = try { - listOf(api.skip(pigeon_instanceArg, nArg)) - } catch (exception: Throwable) { - AndroidLibraryPigeonUtils.wrapError(exception) - } + val wrapped: List = + try { + listOf(api.skip(pigeon_instanceArg, nArg)) + } catch (exception: Throwable) { + AndroidLibraryPigeonUtils.wrapError(exception) + } reply.reply(wrapped) } } else { @@ -972,16 +1074,19 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige @Suppress("LocalVariableName", "FunctionName") /** Creates a Dart instance of InputStream and attaches it to [pigeon_instanceArg]. */ - fun pigeon_newInstance(pigeon_instanceArg: java.io.InputStream, callback: (Result) -> Unit) -{ + fun pigeon_newInstance( + pigeon_instanceArg: java.io.InputStream, + callback: (Result) -> Unit + ) { if (pigeonRegistrar.ignoreCallsToDart) { callback( Result.failure( FlutterError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) - } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + } else if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { callback(Result.success(Unit)) - } else { - val pigeon_identifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + } else { + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) val binaryMessenger = pigeonRegistrar.binaryMessenger val codec = pigeonRegistrar.codec val channelName = "dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance" @@ -989,15 +1094,15 @@ abstract class PigeonApiInputStream(open val pigeonRegistrar: AndroidLibraryPige channel.send(listOf(pigeon_identifierArg)) { if (it is List<*>) { if (it.size > 1) { - callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) + callback( + Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))) } else { callback(Result.success(Unit)) } } else { callback(Result.failure(AndroidLibraryPigeonUtils.createConnectionError(channelName))) - } + } } } } - } diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index 5c8424596c9d..1e2bf3e55127 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -9,7 +9,8 @@ import 'dart:async'; import 'dart:io' show Platform; import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; +import 'package:flutter/foundation.dart' + show ReadBuffer, WriteBuffer, immutable, protected, visibleForTesting; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; @@ -20,7 +21,11 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { +List wrapResponse({ + Object? result, + PlatformException? error, + bool empty = false, +}) { if (empty) { return []; } @@ -29,6 +34,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -40,11 +46,11 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. static DocumentFile Function({required String singleUri})? - documentFile_fromSingleUri; + documentFile_fromSingleUri; /// Overrides [DocumentFile.fromTreeUri]. static DocumentFile Function({required String treeUri})? - documentFile_fromTreeUri; + documentFile_fromTreeUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -69,7 +75,7 @@ abstract class PigeonInternalProxyApiBaseClass { this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -139,9 +145,10 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = {}; + final Map> + _weakInstances = >{}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -154,7 +161,8 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = + _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -162,10 +170,18 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers( + instanceManager: instanceManager, + ); + DocumentFile.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + ContentResolver.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + InputStream.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -182,8 +198,9 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference( + instance, + ); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -244,15 +261,21 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference( + int identifier, + ) { + final PigeonInternalProxyApiBaseClass? weakInstance = + _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = + _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance + .pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = + WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -274,7 +297,10 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + void addHostCreatedInstance( + PigeonInternalProxyApiBaseClass instance, + int identifier, + ) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -303,7 +329,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -316,28 +342,35 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null.', + ); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); + assert( + arg_identifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', + ); try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier!); + (instanceManager ?? PigeonInstanceManager.instance).remove( + arg_identifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -352,8 +385,9 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -396,30 +430,30 @@ class _PigeonInternalInstanceManagerApi { } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference( + readValue(buffer)! as int, + ); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -441,6 +475,7 @@ class _PigeonCodec extends StandardMessageCodec { } } } + /// Representation of a document backed by either a /// android.provider.DocumentsProvider or a raw file on disk. /// @@ -469,8 +504,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String singleUri, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -481,8 +516,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([pigeonVar_instanceIdentifier, singleUri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, singleUri], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -524,8 +560,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String treeUri, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -536,8 +572,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel - .send([pigeonVar_instanceIdentifier, treeUri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, treeUri], + ); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -575,39 +612,46 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -626,8 +670,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -659,8 +704,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -692,8 +738,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -726,8 +773,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -759,8 +807,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -792,8 +841,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -825,8 +875,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -859,8 +910,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -892,8 +944,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -925,8 +978,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -984,39 +1038,46 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1040,8 +1101,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1070,8 +1132,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, uri]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, uri], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1121,39 +1184,46 @@ class InputStream extends PigeonInternalProxyApiBaseClass { }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.'); + assert( + message != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null.', + ); final List args = (message as List?)!; final int? arg_pigeon_instanceIdentifier = (args[0] as int?); - assert(arg_pigeon_instanceIdentifier != null, - 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.'); + assert( + arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', + ); try { (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -1173,8 +1243,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, len]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, len], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1206,8 +1277,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1239,8 +1311,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, n]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, n], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1268,4 +1341,3 @@ class InputStream extends PigeonInternalProxyApiBaseClass { ); } } - From 74d5d046c50da980189178517ca9abc2815bf126 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:31:09 -0500 Subject: [PATCH 176/398] remove runner tests for darwin in cross_file --- .../packages/cross_file_example/MainActivity.kt | 4 ++++ .../ios/Runner.xcodeproj/project.pbxproj | 17 ++++------------- .../example/ios/Runner/AppDelegate.swift | 4 ++++ .../example/ios/Runner/Runner-Bridging-Header.h | 4 ++++ .../example/ios/Runner/SceneDelegate.swift | 4 ++++ .../example/ios/RunnerTests/RunnerTests.swift | 12 ------------ .../cross_file/example/linux/runner/main.cc | 4 ++++ .../example/linux/runner/my_application.cc | 4 ++++ .../example/linux/runner/my_application.h | 4 ++++ .../macos/Runner.xcodeproj/project.pbxproj | 17 ++++------------- .../example/macos/Runner/AppDelegate.swift | 4 ++++ .../macos/Runner/MainFlutterWindow.swift | 4 ++++ .../example/macos/RunnerTests/RunnerTests.swift | 12 ------------ 13 files changed, 44 insertions(+), 50 deletions(-) delete mode 100644 packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift delete mode 100644 packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift diff --git a/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt index df679d6e1ecb..8ef9b9f2e1d8 100644 --- a/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt +++ b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/MainActivity.kt @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + package dev.flutter.packages.cross_file_example import io.flutter.embedding.android.FlutterActivity diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj index df506fc97283..c6bc1f30ab8d 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,7 +8,6 @@ /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; @@ -45,7 +44,6 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; @@ -89,14 +87,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C807B294A618700263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -114,7 +104,6 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, C6869AEB60FAA8D6CEE6FA87 /* Pods */, 9F5AF9B51C64E38CA0A7E19F /* Frameworks */, ); @@ -164,7 +153,6 @@ 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */, FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -341,10 +329,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -372,7 +364,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift b/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift index c30b367ec0a9..81eca8683601 100644 --- a/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift +++ b/packages/cross_file/cross_file/example/ios/Runner/AppDelegate.swift @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import Flutter import UIKit diff --git a/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h b/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h index 308a2a560b42..ba04211afd0a 100644 --- a/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h +++ b/packages/cross_file/cross_file/example/ios/Runner/Runner-Bridging-Header.h @@ -1 +1,5 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #import "GeneratedPluginRegistrant.h" diff --git a/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift b/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift index b9ce8ea2b2ad..8c7b10c639d1 100644 --- a/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift +++ b/packages/cross_file/cross_file/example/ios/Runner/SceneDelegate.swift @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import Flutter import UIKit diff --git a/packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 86a7c3b1b611..000000000000 --- a/packages/cross_file/cross_file/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Flutter -import UIKit -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} diff --git a/packages/cross_file/cross_file/example/linux/runner/main.cc b/packages/cross_file/cross_file/example/linux/runner/main.cc index e7c5c5437037..3b03bbf6941f 100644 --- a/packages/cross_file/cross_file/example/linux/runner/main.cc +++ b/packages/cross_file/cross_file/example/linux/runner/main.cc @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "my_application.h" int main(int argc, char** argv) { diff --git a/packages/cross_file/cross_file/example/linux/runner/my_application.cc b/packages/cross_file/cross_file/example/linux/runner/my_application.cc index 0c853ae28261..2ca8f980ed14 100644 --- a/packages/cross_file/cross_file/example/linux/runner/my_application.cc +++ b/packages/cross_file/cross_file/example/linux/runner/my_application.cc @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "my_application.h" #include diff --git a/packages/cross_file/cross_file/example/linux/runner/my_application.h b/packages/cross_file/cross_file/example/linux/runner/my_application.h index 72271d5e4170..9ae704a9f417 100644 --- a/packages/cross_file/cross_file/example/linux/runner/my_application.h +++ b/packages/cross_file/cross_file/example/linux/runner/my_application.h @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #ifndef FLUTTER_MY_APPLICATION_H_ #define FLUTTER_MY_APPLICATION_H_ diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj index 89936ae96ac4..3527df952cce 100644 --- a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj @@ -22,7 +22,6 @@ /* Begin PBXBuildFile section */ 223056F6078A0B29F9794331 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13AF930B762038462526C125 /* Pods_RunnerTests.framework */; }; - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -65,7 +64,6 @@ 13AF930B762038462526C125 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1791B30977A096C697D5C0C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* cross_file_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cross_file_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -110,14 +108,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 331C80D6294CF71000263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 331C80D7294CF71000263BE5 /* RunnerTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -134,7 +124,6 @@ children = ( 33FAB671232836740065AC1E /* Runner */, 33CEB47122A05771004F2AC0 /* Flutter */, - 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, 3DE641040F107AF7D132DC0F /* Pods */, @@ -195,7 +184,6 @@ A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */, AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -391,10 +379,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -429,7 +421,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift b/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift index b3c176141221..88aaa2ff58ac 100644 --- a/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift +++ b/packages/cross_file/cross_file/example/macos/Runner/AppDelegate.swift @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import Cocoa import FlutterMacOS diff --git a/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift b/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift index 3cc05eb23491..df2443c8ebba 100644 --- a/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift +++ b/packages/cross_file/cross_file/example/macos/Runner/MainFlutterWindow.swift @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import Cocoa import FlutterMacOS diff --git a/packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift deleted file mode 100644 index 61f3bd1fc504..000000000000 --- a/packages/cross_file/cross_file/example/macos/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,12 +0,0 @@ -import Cocoa -import FlutterMacOS -import XCTest - -class RunnerTests: XCTestCase { - - func testExample() { - // If you add code to the Runner application, consider adding tests here. - // See https://developer.apple.com/documentation/xctest for more information about using XCTest. - } - -} From 4352bc6d7fad8daabbcf35b8e2df4cf2d0e1720a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:41:05 -0500 Subject: [PATCH 177/398] fix licenses --- packages/cross_file/cross_file/example/web/index.html | 3 +++ .../cross_file/example/windows/runner/flutter_window.cpp | 4 ++++ .../cross_file/example/windows/runner/flutter_window.h | 4 ++++ .../cross_file/cross_file/example/windows/runner/main.cpp | 4 ++++ .../cross_file/cross_file/example/windows/runner/utils.cpp | 4 ++++ packages/cross_file/cross_file/example/windows/runner/utils.h | 4 ++++ .../cross_file/example/windows/runner/win32_window.cpp | 4 ++++ .../cross_file/example/windows/runner/win32_window.h | 4 ++++ .../packages/cross_file_android/CrossFileAndroidPlugin.kt | 2 +- .../flutter/packages/cross_file_android/ProxyApiRegistrar.kt | 2 +- .../cross_file_android/proxies/ContentResolverProxyApi.kt | 2 +- .../cross_file_android/proxies/DocumentFileProxyApi.kt | 2 +- .../cross_file_android/proxies/InputStreamProxyApi.kt | 2 +- .../packages/cross_file_android/TestProxyApiRegistrar.kt | 2 +- .../cross_file_android/proxies/ContentResolverTest.kt | 2 +- .../packages/cross_file_android/proxies/DocumentFileTest.kt | 2 +- .../packages/cross_file_android/proxies/InputStreamTest.kt | 2 +- .../packages/cross_file_android_example/MainActivity.kt | 4 ++++ .../Sources/cross_file_darwin/CrossFileDarwinPlugin.swift | 2 +- .../apiImplementations/CrossFileDarwinApiImpl.swift | 2 +- .../cross_file_darwin/example/ios/Runner/AppDelegate.swift | 4 ++++ .../example/ios/Runner/Runner-Bridging-Header.h | 4 ++++ .../cross_file_darwin/example/ios/Runner/SceneDelegate.swift | 4 ++++ .../cross_file_darwin/example/macos/Runner/AppDelegate.swift | 4 ++++ .../example/macos/Runner/MainFlutterWindow.swift | 4 ++++ .../lib/cross_file_platform_interface.dart | 2 +- .../lib/src/cross_file_platform.dart | 2 +- .../lib/src/platform_cross_directory.dart | 2 +- .../lib/src/platform_cross_file.dart | 2 +- .../lib/src/platform_cross_file_entity.dart | 2 +- .../platform_scoped_storage_cross_directory.dart | 2 +- .../scoped_storage/platform_scoped_storage_cross_file.dart | 2 +- .../test/cross_file_platform_test.dart | 2 +- packages/cross_file/cross_file_web/example/web/index.html | 3 +++ packages/cross_file/cross_file_web/lib/cross_file_web.dart | 2 +- .../cross_file/cross_file_web/lib/src/cross_file_web.dart | 2 +- .../cross_file/cross_file_web/lib/src/web_cross_file.dart | 2 +- packages/cross_file/cross_file_web/lib/src/web_helpers.dart | 2 +- 38 files changed, 81 insertions(+), 23 deletions(-) diff --git a/packages/cross_file/cross_file/example/web/index.html b/packages/cross_file/cross_file/example/web/index.html index d38ee3a2d575..8030aad1b67f 100644 --- a/packages/cross_file/cross_file/example/web/index.html +++ b/packages/cross_file/cross_file/example/web/index.html @@ -1,4 +1,7 @@ + + + + + + diff --git a/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/DriverExtensionActivity.kt b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/DriverExtensionActivity.kt new file mode 100644 index 000000000000..2e9df8a40f0d --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/cross_file_example/DriverExtensionActivity.kt @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package dev.flutter.packages.cross_file_example + +import io.flutter.embedding.android.FlutterActivity + +/** Test Activity that sets the name of the Dart method entrypoint in the manifest. */ +class DriverExtensionActivity : FlutterActivity() diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart new file mode 100644 index 000000000000..da75ea107bce --- /dev/null +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -0,0 +1,23 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_example/main.dart' as app; +import 'package:flutter_driver/driver_extension.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +/// Entry point for integration tests that require espresso. +@pragma('vm:entry-point') +void integrationTestMain() { + enableFlutterDriverExtension(); + app.main(); +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + // Since this test is lacking integration tests, this test ensures the example + // app can be launched on an emulator/device. + testWidgets('Launch Test', (WidgetTester tester) async {}); +} diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index d62685cd4438..f2ec64784db1 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: mime: ^2.0.0 dev_dependencies: + espresso: ^0.4.0 flutter_test: sdk: flutter integration_test: diff --git a/packages/cross_file/cross_file/example/test_driver/integration_test.dart b/packages/cross_file/cross_file/example/test_driver/integration_test.dart new file mode 100644 index 000000000000..fb3dec00bee9 --- /dev/null +++ b/packages/cross_file/cross_file/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts index e019b79077ea..c67743622fd8 100644 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -45,6 +45,7 @@ android { targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 1c12ae4314ba..70a0cb3657ff 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: video_player: ^2.8.6 dev_dependencies: + espresso: ^0.4.0 flutter_test: sdk: flutter integration_test: diff --git a/packages/cross_file/cross_file_android/example/test_driver/integration_test.dart b/packages/cross_file/cross_file_android/example/test_driver/integration_test.dart new file mode 100644 index 000000000000..fb3dec00bee9 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); From 789ef713a35874a5850cc8072de82f6c07516a4f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 16 Feb 2026 20:42:22 -0500 Subject: [PATCH 190/398] change web to publish to none --- packages/cross_file/cross_file_web/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 9f10f0c94ebd..be96fb10f23e 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -3,6 +3,7 @@ description: Implementation of cross_file_platform_interface for web. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 version: 0.0.1 +publish_to: none environment: sdk: ^3.8.0 From 1b24e783b63e9980d11ff42d6de528b2e0eb1361 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 16 Feb 2026 20:47:41 -0500 Subject: [PATCH 191/398] fix web for wasm --- .../cross_file_web/lib/src/web_cross_file.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart index 02974bb518e6..8ec814d4c4b9 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:convert'; +import 'dart:js_interop'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; @@ -123,8 +124,8 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { @override Future lastModified() async { final Blob blob = await getBlob(); - if (blob is File) { - return DateTime.fromMillisecondsSinceEpoch(blob.lastModified); + if (blob.isA()) { + return DateTime.fromMillisecondsSinceEpoch((blob as File).lastModified); } return null; @@ -159,8 +160,8 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { String? name; if (suggestedName != null) { name = suggestedName; - } else if (blob is File) { - name = blob.name; + } else if (blob.isA()) { + name = (blob as File).name; } downloadObjectUrl(params.uri, name, testOverrides: params.testOverrides); @@ -169,7 +170,7 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { @override Future name() async { final Blob blob = await getBlob(); - return blob is File ? blob.name : null; + return blob.isA() ? (blob as File).name : null; } } From 1d1e949b14b8a21f83b2d0bed5221200dd599bc0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:13:10 -0500 Subject: [PATCH 192/398] formatting --- .../cross_file_example/MainActivityTest.kt | 1 + ...darwin_scoped_storage_cross_file_test.dart | 37 +++++-------------- 2 files changed, 10 insertions(+), 28 deletions(-) diff --git a/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt b/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt index e56d3646e750..9599b8066aa1 100644 --- a/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt +++ b/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt @@ -9,6 +9,7 @@ import dev.flutter.plugins.integration_test.FlutterTestRunner import io.flutter.plugins.DartIntegrationTest import org.junit.Rule import org.junit.runner.RunWith + @DartIntegrationTest @RunWith(FlutterTestRunner::class) class MainActivityTest { diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index e2dc63e5b078..b3222eee9a8d 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -28,68 +28,49 @@ void main() { }); test('lastModified', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.lastModified(), testFile.lastModifiedSync()); }); test('length', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.length(), await testFile.length()); }); test('openRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); - expect( - await file.openRead().toList(), - await testFile.openRead().toList(), - ); + expect(await file.openRead().toList(), await testFile.openRead().toList()); }); test('readAsBytes', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.readAsBytes(), await testFile.readAsBytes()); }); test('readAsString', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.readAsString(), await testFile.readAsString()); }); test('canRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.canRead(), testFile.existsSync()); }); test('exists', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.exists(), testFile.existsSync()); }); test('name', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); expect(await file.name(), 'test_file.txt'); }); From b623ad4b75ee3331f7b8eba155663e8031754453 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:21:07 -0500 Subject: [PATCH 193/398] change settings file to groovy --- .../example/android/settings.gradle | 27 ++++++++++++++++++ .../example/android/settings.gradle.kts | 26 ----------------- .../example/android/settings.gradle | 28 +++++++++++++++++++ .../example/android/settings.gradle.kts | 26 ----------------- 4 files changed, 55 insertions(+), 52 deletions(-) create mode 100644 packages/cross_file/cross_file/example/android/settings.gradle delete mode 100644 packages/cross_file/cross_file/example/android/settings.gradle.kts create mode 100644 packages/cross_file/cross_file_android/example/android/settings.gradle delete mode 100644 packages/cross_file/cross_file_android/example/android/settings.gradle.kts diff --git a/packages/cross_file/cross_file/example/android/settings.gradle b/packages/cross_file/cross_file/example/android/settings.gradle new file mode 100644 index 000000000000..96fce46479f8 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/settings.gradle @@ -0,0 +1,27 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +// See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.11.0" apply false + id "org.jetbrains.kotlin.android" version "2.2.0" apply false + id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.1" +} + +include ":app" diff --git a/packages/cross_file/cross_file/example/android/settings.gradle.kts b/packages/cross_file/cross_file/example/android/settings.gradle.kts deleted file mode 100644 index ca7fe065c167..000000000000 --- a/packages/cross_file/cross_file/example/android/settings.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false -} - -include(":app") diff --git a/packages/cross_file/cross_file_android/example/android/settings.gradle b/packages/cross_file/cross_file_android/example/android/settings.gradle new file mode 100644 index 000000000000..56cb7f02e493 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/settings.gradle @@ -0,0 +1,28 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + }() + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +// See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. +plugins { + id "dev.flutter.flutter-plugin-loader" version "1.0.0" + id "com.android.application" version "8.11.0" apply false + id "org.jetbrains.kotlin.android" version "2.2.0" apply false + id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.1" +} + +include ":app" + diff --git a/packages/cross_file/cross_file_android/example/android/settings.gradle.kts b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts deleted file mode 100644 index fb605bc840f7..000000000000 --- a/packages/cross_file/cross_file_android/example/android/settings.gradle.kts +++ /dev/null @@ -1,26 +0,0 @@ -pluginManagement { - val flutterSdkPath = - run { - val properties = java.util.Properties() - file("local.properties").inputStream().use { properties.load(it) } - val flutterSdkPath = properties.getProperty("flutter.sdk") - require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } - flutterSdkPath - } - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.9.1" apply false - id("org.jetbrains.kotlin.android") version "2.1.0" apply false -} - -include(":app") From f420e80085c46190eaf0945377378149e1b1132b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:24:08 -0500 Subject: [PATCH 194/398] publish too --- packages/cross_file/cross_file_platform_interface/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_platform_interface/pubspec.yaml b/packages/cross_file/cross_file_platform_interface/pubspec.yaml index b0564b9a4139..c8bfd529528d 100644 --- a/packages/cross_file/cross_file_platform_interface/pubspec.yaml +++ b/packages/cross_file/cross_file_platform_interface/pubspec.yaml @@ -5,6 +5,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ # 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: 0.0.1 +publish_to: none environment: sdk: ^3.9.0 From 6415ea649d6fdf7848e00226226aa0f72fa78d39 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 02:56:09 -0500 Subject: [PATCH 195/398] add new files --- .../cross_file_io/example/README.md | 9 + .../cross_file_io/example/lib/main.dart | 122 ++++++++ .../example/linux/CMakeLists.txt | 128 ++++++++ .../example/linux/flutter/CMakeLists.txt | 88 ++++++ .../linux/flutter/generated_plugins.cmake | 23 ++ .../example/linux/runner/CMakeLists.txt | 26 ++ .../example/linux/runner/main.cc | 10 + .../example/linux/runner/my_application.cc | 152 ++++++++++ .../example/linux/runner/my_application.h | 22 ++ .../cross_file_io/example/pubspec.yaml | 49 +++ .../example/windows/CMakeLists.txt | 108 +++++++ .../example/windows/flutter/CMakeLists.txt | 109 +++++++ .../windows/flutter/generated_plugins.cmake | 23 ++ .../example/windows/runner/CMakeLists.txt | 40 +++ .../example/windows/runner/Runner.rc | 121 ++++++++ .../example/windows/runner/flutter_window.cpp | 73 +++++ .../example/windows/runner/flutter_window.h | 37 +++ .../example/windows/runner/main.cpp | 46 +++ .../example/windows/runner/resource.h | 16 + .../windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes .../windows/runner/runner.exe.manifest | 14 + .../example/windows/runner/utils.cpp | 69 +++++ .../example/windows/runner/utils.h | 23 ++ .../example/windows/runner/win32_window.cpp | 284 ++++++++++++++++++ .../example/windows/runner/win32_window.h | 104 +++++++ 25 files changed, 1696 insertions(+) create mode 100644 packages/cross_file/cross_file_io/example/README.md create mode 100644 packages/cross_file/cross_file_io/example/lib/main.dart create mode 100644 packages/cross_file/cross_file_io/example/linux/CMakeLists.txt create mode 100644 packages/cross_file/cross_file_io/example/linux/flutter/CMakeLists.txt create mode 100644 packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake create mode 100644 packages/cross_file/cross_file_io/example/linux/runner/CMakeLists.txt create mode 100644 packages/cross_file/cross_file_io/example/linux/runner/main.cc create mode 100644 packages/cross_file/cross_file_io/example/linux/runner/my_application.cc create mode 100644 packages/cross_file/cross_file_io/example/linux/runner/my_application.h create mode 100644 packages/cross_file/cross_file_io/example/pubspec.yaml create mode 100644 packages/cross_file/cross_file_io/example/windows/CMakeLists.txt create mode 100644 packages/cross_file/cross_file_io/example/windows/flutter/CMakeLists.txt create mode 100644 packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/CMakeLists.txt create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/Runner.rc create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/flutter_window.cpp create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/flutter_window.h create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/main.cpp create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/resource.h create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/resources/app_icon.ico create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/runner.exe.manifest create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/utils.cpp create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/utils.h create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/win32_window.cpp create mode 100644 packages/cross_file/cross_file_io/example/windows/runner/win32_window.h diff --git a/packages/cross_file/cross_file_io/example/README.md b/packages/cross_file/cross_file_io/example/README.md new file mode 100644 index 000000000000..96b8bb17dbff --- /dev/null +++ b/packages/cross_file/cross_file_io/example/README.md @@ -0,0 +1,9 @@ +# Platform Implementation Test App + +This is a test app for manual testing and automated integration testing +of this platform implementation. It is not intended to demonstrate actual use of +this package, since the intent is that plugin clients use the app-facing +package. + +Unless you are making changes to this implementation package, this example is +very unlikely to be relevant. diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart new file mode 100644 index 000000000000..244a702cf925 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -0,0 +1,122 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + // This widget is the root of your application. + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Flutter Demo', + theme: ThemeData( + // This is the theme of your application. + // + // TRY THIS: Try running your application with "flutter run". You'll see + // the application has a purple toolbar. Then, without quitting the app, + // try changing the seedColor in the colorScheme below to Colors.green + // and then invoke "hot reload" (save your changes or press the "hot + // reload" button in a Flutter-supported IDE, or press "r" if you used + // the command line to start the app). + // + // Notice that the counter didn't reset back to zero; the application + // state is not lost during the reload. To reset the state, use hot + // restart instead. + // + // This works for code too, not just values: Most code changes can be + // tested with just a hot reload. + colorScheme: .fromSeed(seedColor: Colors.deepPurple), + ), + home: const MyHomePage(title: 'Flutter Demo Home Page'), + ); + } +} + +class MyHomePage extends StatefulWidget { + const MyHomePage({super.key, required this.title}); + + // This widget is the home page of your application. It is stateful, meaning + // that it has a State object (defined below) that contains fields that affect + // how it looks. + + // This class is the configuration for the state. It holds the values (in this + // case the title) provided by the parent (in this case the App widget) and + // used by the build method of the State. Fields in a Widget subclass are + // always marked "final". + + final String title; + + @override + State createState() => _MyHomePageState(); +} + +class _MyHomePageState extends State { + int _counter = 0; + + void _incrementCounter() { + setState(() { + // This call to setState tells the Flutter framework that something has + // changed in this State, which causes it to rerun the build method below + // so that the display can reflect the updated values. If we changed + // _counter without calling setState(), then the build method would not be + // called again, and so nothing would appear to happen. + _counter++; + }); + } + + @override + Widget build(BuildContext context) { + // This method is rerun every time setState is called, for instance as done + // by the _incrementCounter method above. + // + // The Flutter framework has been optimized to make rerunning build methods + // fast, so that you can just rebuild anything that needs updating rather + // than having to individually change instances of widgets. + return Scaffold( + appBar: AppBar( + // TRY THIS: Try changing the color here to a specific color (to + // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar + // change color while the other colors stay the same. + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), + ), + body: Center( + // Center is a layout widget. It takes a single child and positions it + // in the middle of the parent. + child: Column( + // Column is also a layout widget. It takes a list of children and + // arranges them vertically. By default, it sizes itself to fit its + // children horizontally, and tries to be as tall as its parent. + // + // Column has various properties to control how it sizes itself and + // how it positions its children. Here we use mainAxisAlignment to + // center the children vertically; the main axis here is the vertical + // axis because Columns are vertical (the cross axis would be + // horizontal). + // + // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" + // action in the IDE, or press "p" in the console), to see the + // wireframe for each widget. + mainAxisAlignment: .center, + children: [ + const Text('You have pushed the button this many times:'), + Text( + '$_counter', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _incrementCounter, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} diff --git a/packages/cross_file/cross_file_io/example/linux/CMakeLists.txt b/packages/cross_file/cross_file_io/example/linux/CMakeLists.txt new file mode 100644 index 000000000000..4051d516c369 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/CMakeLists.txt @@ -0,0 +1,128 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "cross_file_io_example") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "dev.flutter.packages.cross_file_io_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/packages/cross_file/cross_file_io/example/linux/flutter/CMakeLists.txt b/packages/cross_file/cross_file_io/example/linux/flutter/CMakeLists.txt new file mode 100644 index 000000000000..d5bd01648a96 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake b/packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000000..2e1de87a7eb6 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/cross_file/cross_file_io/example/linux/runner/CMakeLists.txt b/packages/cross_file/cross_file_io/example/linux/runner/CMakeLists.txt new file mode 100644 index 000000000000..e97dabc7028e --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/packages/cross_file/cross_file_io/example/linux/runner/main.cc b/packages/cross_file/cross_file_io/example/linux/runner/main.cc new file mode 100644 index 000000000000..3b03bbf6941f --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/runner/main.cc @@ -0,0 +1,10 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/packages/cross_file/cross_file_io/example/linux/runner/my_application.cc b/packages/cross_file/cross_file_io/example/linux/runner/my_application.cc new file mode 100644 index 000000000000..3cfefd6ab07d --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/runner/my_application.cc @@ -0,0 +1,152 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Called when first Flutter frame received. +static void first_frame_cb(MyApplication* self, FlView* view) { + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); +} + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "cross_file_io_example"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "cross_file_io_example"); + } + + gtk_window_set_default_size(window, 1280, 720); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + GdkRGBA background_color; + // Background defaults to black, override it here if necessary, e.g. #00000000 + // for transparent. + gdk_rgba_parse(&background_color, "#000000"); + fl_view_set_background_color(view, &background_color); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + // Show the window when Flutter renders. + // Requires the view to be realized so we can start rendering. + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), + self); + gtk_widget_realize(GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); +} diff --git a/packages/cross_file/cross_file_io/example/linux/runner/my_application.h b/packages/cross_file/cross_file_io/example/linux/runner/my_application.h new file mode 100644 index 000000000000..9ae704a9f417 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/linux/runner/my_application.h @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/packages/cross_file/cross_file_io/example/pubspec.yaml b/packages/cross_file/cross_file_io/example/pubspec.yaml new file mode 100644 index 000000000000..514ca2399245 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/pubspec.yaml @@ -0,0 +1,49 @@ +name: cross_file_io_example +description: Demonstrates how to use cross files. +publish_to: none + +environment: + sdk: ^3.9.0 + flutter: ">=3.35.0" + +dependencies: + cross_file: + # When depending on this package from a real application you should use: + # cross_file: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file + file_selector: + git: + url: https://github.com/bparrishMines/packages + ref: new_file_selector + path: packages/file_selector/file_selector + flutter: + sdk: flutter + flutter_driver: + sdk: flutter + mime: ^2.0.0 + +dev_dependencies: + flutter_test: + sdk: flutter + integration_test: + sdk: flutter + +flutter: + uses-material-design: true + assets: + - assets/hello.txt + +dependency_overrides: + cross_file_io: + # When depending on this package from a real application you should use: + # cross_file_io: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ \ No newline at end of file diff --git a/packages/cross_file/cross_file_io/example/windows/CMakeLists.txt b/packages/cross_file/cross_file_io/example/windows/CMakeLists.txt new file mode 100644 index 000000000000..ed83df53f0e0 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(cross_file_io_example LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "cross_file_io_example") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/packages/cross_file/cross_file_io/example/windows/flutter/CMakeLists.txt b/packages/cross_file/cross_file_io/example/windows/flutter/CMakeLists.txt new file mode 100644 index 000000000000..903f4899d6fc --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake b/packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake new file mode 100644 index 000000000000..b93c4c30c167 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/packages/cross_file/cross_file_io/example/windows/runner/CMakeLists.txt b/packages/cross_file/cross_file_io/example/windows/runner/CMakeLists.txt new file mode 100644 index 000000000000..394917c053a0 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/packages/cross_file/cross_file_io/example/windows/runner/Runner.rc b/packages/cross_file/cross_file_io/example/windows/runner/Runner.rc new file mode 100644 index 000000000000..62d29e0fb8e7 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "dev.flutter.packages" "\0" + VALUE "FileDescription", "cross_file_io_example" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "cross_file_io_example" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 dev.flutter.packages. All rights reserved." "\0" + VALUE "OriginalFilename", "cross_file_io_example.exe" "\0" + VALUE "ProductName", "cross_file_io_example" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/packages/cross_file/cross_file_io/example/windows/runner/flutter_window.cpp b/packages/cross_file/cross_file_io/example/windows/runner/flutter_window.cpp new file mode 100644 index 000000000000..d765fd5d5ef1 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/flutter_window.cpp @@ -0,0 +1,73 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { this->Show(); }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/packages/cross_file/cross_file_io/example/windows/runner/flutter_window.h b/packages/cross_file/cross_file_io/example/windows/runner/flutter_window.h new file mode 100644 index 000000000000..2ef41dd2f67a --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/flutter_window.h @@ -0,0 +1,37 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/packages/cross_file/cross_file_io/example/windows/runner/main.cpp b/packages/cross_file/cross_file_io/example/windows/runner/main.cpp new file mode 100644 index 000000000000..a1eb914b2f89 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/main.cpp @@ -0,0 +1,46 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t* command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"cross_file_io_example", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/packages/cross_file/cross_file_io/example/windows/runner/resource.h b/packages/cross_file/cross_file_io/example/windows/runner/resource.h new file mode 100644 index 000000000000..d5d958dc4257 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/packages/cross_file/cross_file_io/example/windows/runner/resources/app_icon.ico b/packages/cross_file/cross_file_io/example/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/packages/cross_file/cross_file_io/example/windows/runner/runner.exe.manifest b/packages/cross_file/cross_file_io/example/windows/runner/runner.exe.manifest new file mode 100644 index 000000000000..153653e8d67f --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/packages/cross_file/cross_file_io/example/windows/runner/utils.cpp b/packages/cross_file/cross_file_io/example/windows/runner/utils.cpp new file mode 100644 index 000000000000..9db5336111ab --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/utils.cpp @@ -0,0 +1,69 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE* unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = + ::WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, -1, + nullptr, 0, nullptr, nullptr) - + 1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, input_length, + utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/packages/cross_file/cross_file_io/example/windows/runner/utils.h b/packages/cross_file/cross_file_io/example/windows/runner/utils.h new file mode 100644 index 000000000000..24279736b321 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/utils.h @@ -0,0 +1,23 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/packages/cross_file/cross_file_io/example/windows/runner/win32_window.cpp b/packages/cross_file/cross_file_io/example/windows/runner/win32_window.cpp new file mode 100644 index 000000000000..6ee06d751984 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/win32_window.cpp @@ -0,0 +1,284 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: +/// https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = + L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { ++g_active_window_count; } + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { return ShowWindow(window_handle_, SW_SHOWNORMAL); } + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { return window_handle_; } + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = + RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, RRF_RT_REG_DWORD, nullptr, + &light_mode, &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/packages/cross_file/cross_file_io/example/windows/runner/win32_window.h b/packages/cross_file/cross_file_io/example/windows/runner/win32_window.h new file mode 100644 index 000000000000..1b5ff6023fb2 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/windows/runner/win32_window.h @@ -0,0 +1,104 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_ From 00a9f10ce10c0d1842379e56e3e763f5b4435704 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 02:58:06 -0500 Subject: [PATCH 196/398] add example app --- .../cross_file_io/example/assets/hello.txt | 1 + .../integration_test/cross_file_test.dart | 23 ++ .../cross_file_io/example/lib/main.dart | 199 +++++++++--------- .../example/test_driver/integration_test.dart | 7 + 4 files changed, 136 insertions(+), 94 deletions(-) create mode 100644 packages/cross_file/cross_file_io/example/assets/hello.txt create mode 100644 packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart create mode 100644 packages/cross_file/cross_file_io/example/test_driver/integration_test.dart diff --git a/packages/cross_file/cross_file_io/example/assets/hello.txt b/packages/cross_file/cross_file_io/example/assets/hello.txt new file mode 100644 index 000000000000..5dd01c177f5d --- /dev/null +++ b/packages/cross_file/cross_file_io/example/assets/hello.txt @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart new file mode 100644 index 000000000000..3bd057deec87 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart @@ -0,0 +1,23 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_io_example/main.dart' as app; +import 'package:flutter_driver/driver_extension.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:integration_test/integration_test.dart'; + +/// Entry point for integration tests that require espresso. +@pragma('vm:entry-point') +void integrationTestMain() { + enableFlutterDriverExtension(); + app.main(); +} + +void main() { + IntegrationTestWidgetsFlutterBinding.ensureInitialized(); + + // Since this test is lacking integration tests, this test ensures the example + // app can be launched on an emulator/device. + testWidgets('Launch Test', (WidgetTester tester) async {}); +} diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart index 244a702cf925..29b1369ba4da 100644 --- a/packages/cross_file/cross_file_io/example/lib/main.dart +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -1,122 +1,133 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; +import 'package:mime/mime.dart' as mime; void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({super.key}); - - // This widget is the root of your application. - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - // This is the theme of your application. - // - // TRY THIS: Try running your application with "flutter run". You'll see - // the application has a purple toolbar. Then, without quitting the app, - // try changing the seedColor in the colorScheme below to Colors.green - // and then invoke "hot reload" (save your changes or press the "hot - // reload" button in a Flutter-supported IDE, or press "r" if you used - // the command line to start the app). - // - // Notice that the counter didn't reset back to zero; the application - // state is not lost during the reload. To reset the state, use hot - // restart instead. - // - // This works for code too, not just values: Most code changes can be - // tested with just a hot reload. - colorScheme: .fromSeed(seedColor: Colors.deepPurple), - ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), - ); - } + runApp(const MaterialApp(home: FileOpenScreen())); } -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); +/// Example screen to open a file selector and display it. +class FileOpenScreen extends StatelessWidget { + /// Constructs a [FileOpenScreen]. + const FileOpenScreen({super.key}); - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. + Future _openFile(BuildContext context) async { + final XFile? file = await openFile(); - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". + if (file != null) { + final String filename = await file.name() ?? file.uri; - final String title; + switch (mime.lookupMimeType(filename)) { + case final String mimeType when mimeType.startsWith('text'): + final String fileContents = await file.readAsString(); + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(filename: filename, fileContents: fileContents), + ); + } + case _: + debugPrint('File Uri: ${file.uri}'); + debugPrint('Filename: $filename'); + debugPrint('Can Read File: ${await file.canRead()}'); + debugPrint('File Length: ${await file.length()}'); + debugPrint('File Last Modified: ${await file.lastModified()}'); + return; + } + } else { + debugPrint('No file selected.'); + } + } - @override - State createState() => _MyHomePageState(); -} + Future _openDirectory() async { + final XDirectory? directory = await getDirectoryPath(); -class _MyHomePageState extends State { - int _counter = 0; + if (directory != null) { + debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory exists: ${await directory.exists()}'); - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); + debugPrint('List of Entities:'); + await for (final XFileEntity entity in directory.list()) { + switch (entity) { + case final XFile file: + final String filename = await file.name() ?? file.uri; + debugPrint('\tFile: $filename'); + case final XDirectory directory: + debugPrint('\tDirectory: ${directory.uri}'); + } + } + } else { + debugPrint('No directory selected.'); + } } @override Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. return Scaffold( appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), + title: const Text('Open a File'), + backgroundColor: Colors.blue, ), body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: .center, - children: [ - const Text('You have pushed the button this many times:'), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open Directory'), + onPressed: () => _openDirectory(), ), ], ), ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), + ); + } +} + +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay({ + super.key, + required this.filename, + required this.fileContents, + }); + + /// The name of the file. + final String filename; + + /// The contents of the file. + final String fileContents; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(filename), + content: Scrollbar( + child: SingleChildScrollView(child: Text(fileContents)), ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], ); } } diff --git a/packages/cross_file/cross_file_io/example/test_driver/integration_test.dart b/packages/cross_file/cross_file_io/example/test_driver/integration_test.dart new file mode 100644 index 000000000000..fb3dec00bee9 --- /dev/null +++ b/packages/cross_file/cross_file_io/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); From 5fc9cd58ce3e0c35f71a8a9ead456defbb502a16 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:10:54 -0500 Subject: [PATCH 197/398] update project gradles --- .../example/android/app/build.gradle | 68 +++++++++++++++++++ .../example/android/app/build.gradle.kts | 52 -------------- .../example/android/app/build.gradle | 68 +++++++++++++++++++ .../example/android/app/build.gradle.kts | 67 ------------------ 4 files changed, 136 insertions(+), 119 deletions(-) create mode 100644 packages/cross_file/cross_file/example/android/app/build.gradle delete mode 100644 packages/cross_file/cross_file/example/android/app/build.gradle.kts create mode 100644 packages/cross_file/cross_file_android/example/android/app/build.gradle delete mode 100644 packages/cross_file/cross_file_android/example/android/app/build.gradle.kts diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle b/packages/cross_file/cross_file/example/android/app/build.gradle new file mode 100644 index 000000000000..d1a654b282e9 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/build.gradle @@ -0,0 +1,68 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace = "dev.flutter.packages.cross_file_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + applicationId "dev.flutter.packages.cross_file_example" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + signingConfig = signingConfigs.debug + } + } +} + +flutter { + source = '../..' +} + +dependencies { + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test:runner:1.2.0") + androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") + api("androidx.test:core:1.4.0") +} diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle.kts b/packages/cross_file/cross_file/example/android/app/build.gradle.kts deleted file mode 100644 index de0c07014d0a..000000000000 --- a/packages/cross_file/cross_file/example/android/app/build.gradle.kts +++ /dev/null @@ -1,52 +0,0 @@ -plugins { - id("com.android.application") - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -android { - namespace = "dev.flutter.packages.cross_file_example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId = "dev.flutter.packages.cross_file_example" - // You can update the following values to match your application needs. - // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") - } - } -} - -flutter { - source = "../.." -} - -dependencies { - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test:runner:1.2.0") - androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") - api("androidx.test:core:1.4.0") -} diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle b/packages/cross_file/cross_file_android/example/android/app/build.gradle new file mode 100644 index 000000000000..fbe0ce9a9178 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle @@ -0,0 +1,68 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace = "dev.flutter.packages.cross_file_android_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + applicationId "dev.flutter.packages.cross_file_android_example" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + signingConfig = signingConfigs.debug + } + } +} + +flutter { + source = '../..' +} + +dependencies { + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test:runner:1.2.0") + androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") + api("androidx.test:core:1.4.0") +} diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts deleted file mode 100644 index c67743622fd8..000000000000 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts +++ /dev/null @@ -1,67 +0,0 @@ -import java.util.Properties - -plugins { - id("com.android.application") - id("kotlin-android") - // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. - id("dev.flutter.flutter-gradle-plugin") -} - -val localProperties = Properties() -val localPropertiesFile = rootProject.file("local.properties") - -if (localPropertiesFile.exists()) { - localPropertiesFile.reader(Charsets.UTF_8).use { reader -> - localProperties.load(reader) - } -} - -val flutterVersionCode: String = localProperties.getProperty("flutter.versionCode") ?: "1" -val flutterVersionName: String = localProperties.getProperty("flutter.versionName") ?: "1.0" - -android { - namespace = "dev.flutter.packages.cross_file_android_example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - sourceSets { - getByName("main") { - java.srcDirs("src/main/kotlin") - } - } - - defaultConfig { - applicationId = "dev.flutter.packages.cross_file_android_example" - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode = flutter.versionCode - versionName = flutter.versionName - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - signingConfig = signingConfigs.getByName("debug") - } - } -} - -dependencies { - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test:runner:1.2.0") - androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") - api("androidx.test:core:1.4.0") -} - -flutter { - source = "../.." -} From 79a98cbca25ad607147d36e0e1e743deeffb8314 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:15:17 -0500 Subject: [PATCH 198/398] add dart integration test file --- .../io/flutter/plugins/DartIntegrationTest.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 packages/cross_file/cross_file/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt diff --git a/packages/cross_file/cross_file/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt new file mode 100644 index 000000000000..5d0a4557390d --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/src/main/kotlin/io/flutter/plugins/DartIntegrationTest.kt @@ -0,0 +1,16 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package io.flutter.plugins + +/* + * Annotation to aid repository tooling in determining if a test is + * a native java unit test or a java class with a dart integration. + * + * See: https://github.com/flutter/flutter/blob/master/docs/ecosystem/testing/Plugin-Tests.md#enabling-android-ui-tests + * for more information. + */ +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS) +annotation class DartIntegrationTest From fe48304b5430a41185b9bdcd1b4edef91e013277 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:32:01 -0500 Subject: [PATCH 199/398] improve pubspecs and add test drivers --- .../example/integration_test/cross_file_test.dart | 9 --------- packages/cross_file/cross_file/example/pubspec.yaml | 2 -- .../integration_test/cross_file_android_test.dart} | 0 .../cross_file/cross_file_android/example/pubspec.yaml | 3 --- packages/cross_file/cross_file_android/pubspec.yaml | 2 +- .../integration_test/cross_file_darwin_test.dart} | 0 .../example/test_driver/integration_test.dart | 7 +++++++ .../{cross_file_test.dart => cross_file_io_test.dart} | 9 --------- packages/cross_file/cross_file_io/example/pubspec.yaml | 2 -- .../example/integration_test/cross_file_web_test.dart} | 9 --------- packages/cross_file/cross_file_web/example/pubspec.yaml | 5 ++--- .../example/test_driver/integration_test.dart | 7 +++++++ packages/cross_file/cross_file_web/pubspec.yaml | 4 ++-- 13 files changed, 19 insertions(+), 40 deletions(-) rename packages/cross_file/{cross_file_darwin/example/integration_test/plugin_integration_test.dart => cross_file_android/example/integration_test/cross_file_android_test.dart} (100%) rename packages/cross_file/{cross_file_web/example/integration_test/plugin_integration_test.dart => cross_file_darwin/example/integration_test/cross_file_darwin_test.dart} (100%) create mode 100644 packages/cross_file/cross_file_darwin/example/test_driver/integration_test.dart rename packages/cross_file/cross_file_io/example/integration_test/{cross_file_test.dart => cross_file_io_test.dart} (64%) rename packages/cross_file/{cross_file_android/example/integration_test/plugin_integration_test.dart => cross_file_web/example/integration_test/cross_file_web_test.dart} (64%) create mode 100644 packages/cross_file/cross_file_web/example/test_driver/integration_test.dart diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart index da75ea107bce..621977be68c7 100644 --- a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -2,18 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_example/main.dart' as app; -import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -/// Entry point for integration tests that require espresso. -@pragma('vm:entry-point') -void integrationTestMain() { - enableFlutterDriverExtension(); - app.main(); -} - void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index f2ec64784db1..c6c82bb4cc80 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -34,8 +34,6 @@ dependencies: path: packages/file_selector/file_selector flutter: sdk: flutter - flutter_driver: - sdk: flutter mime: ^2.0.0 dev_dependencies: diff --git a/packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_android/example/integration_test/cross_file_android_test.dart similarity index 100% rename from packages/cross_file/cross_file_darwin/example/integration_test/plugin_integration_test.dart rename to packages/cross_file/cross_file_android/example/integration_test/cross_file_android_test.dart diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 70a0cb3657ff..748f4c2630b6 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -14,10 +14,7 @@ dependencies: path: packages/file_selector/file_selector flutter: sdk: flutter - flutter_driver: - sdk: flutter mime: ^2.0.0 - video_player: ^2.8.6 dev_dependencies: espresso: ^0.4.0 diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 8772bebde15b..5a44fa747dce 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -37,7 +37,7 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.4.4 - pigeon: ^26.1.4 + pigeon: ^26.1.7 topics: - file diff --git a/packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart similarity index 100% rename from packages/cross_file/cross_file_web/example/integration_test/plugin_integration_test.dart rename to packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart diff --git a/packages/cross_file/cross_file_darwin/example/test_driver/integration_test.dart b/packages/cross_file/cross_file_darwin/example/test_driver/integration_test.dart new file mode 100644 index 000000000000..fb3dec00bee9 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart similarity index 64% rename from packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart rename to packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart index 3bd057deec87..621977be68c7 100644 --- a/packages/cross_file/cross_file_io/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart @@ -2,18 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_io_example/main.dart' as app; -import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -/// Entry point for integration tests that require espresso. -@pragma('vm:entry-point') -void integrationTestMain() { - enableFlutterDriverExtension(); - app.main(); -} - void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); diff --git a/packages/cross_file/cross_file_io/example/pubspec.yaml b/packages/cross_file/cross_file_io/example/pubspec.yaml index 514ca2399245..6ec7185edcd1 100644 --- a/packages/cross_file/cross_file_io/example/pubspec.yaml +++ b/packages/cross_file/cross_file_io/example/pubspec.yaml @@ -24,8 +24,6 @@ dependencies: path: packages/file_selector/file_selector flutter: sdk: flutter - flutter_driver: - sdk: flutter mime: ^2.0.0 dev_dependencies: diff --git a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart b/packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart similarity index 64% rename from packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart rename to packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart index 7a43ba37cc41..621977be68c7 100644 --- a/packages/cross_file/cross_file_android/example/integration_test/plugin_integration_test.dart +++ b/packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart @@ -2,18 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_android_example/main.dart' as app; -import 'package:flutter_driver/driver_extension.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -/// Entry point for integration tests that require espresso. -@pragma('vm:entry-point') -void integrationTestMain() { - enableFlutterDriverExtension(); - app.main(); -} - void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index a88c55a7a699..61148b45c75b 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -2,8 +2,8 @@ name: cross_file_web_example publish_to: none environment: - sdk: ^3.8.0 - flutter: ">=3.32.0" + sdk: ^3.9.0 + flutter: ">=3.35.0" dependencies: file_selector: @@ -14,7 +14,6 @@ dependencies: flutter: sdk: flutter mime: ^2.0.0 - web: ^1.0.0 dev_dependencies: flutter_test: diff --git a/packages/cross_file/cross_file_web/example/test_driver/integration_test.dart b/packages/cross_file/cross_file_web/example/test_driver/integration_test.dart new file mode 100644 index 000000000000..fb3dec00bee9 --- /dev/null +++ b/packages/cross_file/cross_file_web/example/test_driver/integration_test.dart @@ -0,0 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:integration_test/integration_test_driver.dart'; + +Future main() => integrationDriver(); diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index be96fb10f23e..7da5af76eaf6 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -6,8 +6,8 @@ version: 0.0.1 publish_to: none environment: - sdk: ^3.8.0 - flutter: ">=3.32.0" + sdk: ^3.9.0 + flutter: ">=3.35.0" flutter: plugin: From 8a5d3cc05adf6ae8d7888ad898a5c434324987a8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:39:04 -0500 Subject: [PATCH 200/398] fix darwin tests --- .../darwin/Tests/CrossFileDarwinApiTests.swift | 2 +- .../example/macos/Runner.xcodeproj/project.pbxproj | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 2cf1040bffdc..26451f70e45d 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -46,6 +46,6 @@ struct CrossFileDarwinApiTests { let api = CrossFileDarwinApiImpl() let bookmarkedURLString = try! api.tryCreateBookmarkedUrl(url: testFileURL.absoluteString)! - #expect(URL(fileURLWithPath: bookmarkedURLString) == testFileURL) + #expect(bookmarkedURLString == testFileURL.absoluteString) } } diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index ce4c04d9e025..735b9856137d 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -390,14 +390,10 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); - outputPaths = ( - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; From a234ecd0a47b95f196418ee04423d6c24a9204d4 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:36:34 -0500 Subject: [PATCH 201/398] update interface --- .../lib/src/cross_file_platform.dart | 37 +++++++++- .../lib/src/platform_cross_file.dart | 3 - .../platform_scoped_storage_cross_file.dart | 3 + .../test/cross_file_platform_test.dart | 71 +++++-------------- ...art => web_scoped_storage_cross_file.dart} | 0 5 files changed, 56 insertions(+), 58 deletions(-) rename packages/cross_file/cross_file_web/lib/src/{web_cross_file.dart => web_scoped_storage_cross_file.dart} (100%) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index c10a8ab4cedf..9ae461bd324a 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -21,7 +21,9 @@ abstract base class CrossFilePlatform { static CrossFilePlatform? instance; /// Creates a new [PlatformXFile]. - PlatformXFile createPlatformXFile(PlatformXFileCreationParams params); + PlatformXFile createPlatformXFile(PlatformXFileCreationParams params) { + return _DefaultXFile(params); + } /// Creates a new [PlatformXDirectory]. PlatformXDirectory createPlatformXDirectory( @@ -45,6 +47,39 @@ abstract base class CrossFilePlatform { } } +/// Implementation of [PlatformXFile} that represents a resource that does not +/// exist. +final class _DefaultXFile extends PlatformXFile { + _DefaultXFile(super.params) : super.implementation(); + + @override + Future exists() async => false; + + @override + Future lastModified() async => null; + + @override + Future length() async => null; + + @override + Future name() async => null; + + @override + Stream openRead([int? start, int? end]) { + throw UnsupportedError('This instance does not represent any resource.'); + } + + @override + Future readAsBytes() { + throw UnsupportedError('This instance does not represent any resource.'); + } + + @override + Future readAsString({Encoding encoding = utf8}) { + throw UnsupportedError('This instance does not represent any resource.'); + } +} + /// Implementation of [PlatformXDirectory} that represents a directory that does /// not exist. final class _DefaultXDirectory extends PlatformXDirectory { diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 3b878be7fe77..cfbcab742471 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -105,9 +105,6 @@ abstract base class PlatformXFile extends PlatformXFileEntity { /// Returns null if file doesn't exist or information is not available. Future length(); - /// Whether the resource represented by this reference can be read. - Future canRead(); - /// Creates a new independent Stream for the contents of this resource. /// /// If start is present, the file will be read from byte-offset start. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index 46c83c3aae81..f35774771860 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -97,4 +97,7 @@ abstract base class PlatformScopedStorageXFile extends PlatformXFile { @override PlatformScopedStorageXFileCreationParams get params => super.params as PlatformScopedStorageXFileCreationParams; + + /// Whether the resource represented by this reference can be read. + Future canRead(); } diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 0ece34bcafee..aeab62ccae30 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -2,15 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:convert'; - -import 'dart:typed_data'; - import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { group('CrossFilePlatform', () { + test( + 'Default implementation of createPlatformXFile should return an implementation that returns false for exists()', + () async { + final platform = TestCrossFilePlatform(); + + expect( + await platform + .createPlatformXFile( + const PlatformXFileCreationParams(uri: 'test'), + ) + .exists(), + false, + ); + }, + ); + test( 'Default implementation of createPlatformXDirectory should return an implementation that returns false for exists()', () async { @@ -63,53 +75,4 @@ void main() { }); } -final class TestCrossFilePlatform extends CrossFilePlatform { - @override - PlatformXFile createPlatformXFile(PlatformXFileCreationParams params) { - return TestXFile(params); - } -} - -final class TestXFile extends PlatformXFile { - TestXFile(super.params) : super.implementation(); - - @override - Future canRead() { - throw UnimplementedError(); - } - - @override - Future exists() { - throw UnimplementedError(); - } - - @override - Future lastModified() { - throw UnimplementedError(); - } - - @override - Future length() { - throw UnimplementedError(); - } - - @override - Stream openRead([int? start, int? end]) { - throw UnimplementedError(); - } - - @override - Future readAsBytes() { - throw UnimplementedError(); - } - - @override - Future readAsString({Encoding encoding = utf8}) { - throw UnimplementedError(); - } - - @override - Future name() { - throw UnimplementedError(); - } -} +final class TestCrossFilePlatform extends CrossFilePlatform {} diff --git a/packages/cross_file/cross_file_web/lib/src/web_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart similarity index 100% rename from packages/cross_file/cross_file_web/lib/src/web_cross_file.dart rename to packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart From 9765b615cda7ac67c85dd3768671debb6c7e1cb3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:42:56 -0500 Subject: [PATCH 202/398] web update --- .../cross_file_web/example/lib/main.dart | 4 +- .../cross_file_web/lib/cross_file_web.dart | 3 +- .../lib/src/cross_file_web.dart | 8 +- .../src/web_scoped_storage_cross_file.dart | 74 ++++++++++-------- .../test/web_cross_file_test.dart | 76 ++++++++++++------- 5 files changed, 100 insertions(+), 65 deletions(-) diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index 4ffd44234094..afcf367f6096 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -34,7 +34,9 @@ class FileOpenScreen extends StatelessWidget { case _: debugPrint('File Uri: ${file.uri}'); debugPrint('Filename: $filename'); - debugPrint('Can Read File: ${await file.canRead()}'); + if (file is ScopedStorageXFile) { + debugPrint('Can Read File: ${await file.canRead()}'); + } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index d634bccb57fa..6785103cd2fb 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -6,4 +6,5 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show CrossFilePlatform, PlatformXFileCreationParams; export 'src/cross_file_web.dart'; -export 'src/web_cross_file.dart' show WebXFileCreationParams, WebXFileExtension; +export 'src/web_scoped_storage_cross_file.dart' + show WebScopedStorageXFileCreationParams, WebScopedStorageXFileExtension; diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart index 3c391370c395..5559639b05c3 100644 --- a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -5,7 +5,7 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; -import 'web_cross_file.dart'; +import 'web_scoped_storage_cross_file.dart'; /// Implementation of [CrossFilePlatform] for web. base class CrossFileWeb extends CrossFilePlatform { @@ -15,7 +15,9 @@ base class CrossFileWeb extends CrossFilePlatform { } @override - WebXFile createPlatformXFile(PlatformXFileCreationParams params) { - return WebXFile(params); + WebScopedStorageXFile createPlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, + ) { + return WebScopedStorageXFile(params); } } diff --git a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart index 8ec814d4c4b9..64a093852025 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart @@ -11,33 +11,37 @@ import 'package:web/web.dart'; import 'web_helpers.dart'; -/// Base implementation of [PlatformXFileCreationParams] for web. +/// Base implementation of [PlatformScopedStorageXFileCreationParams] for web. @immutable -sealed class WebXFileCreationParams extends PlatformXFileCreationParams { - /// Constructs a [WebXFileCreationParams]. - const WebXFileCreationParams({required super.uri, this.testOverrides}); +sealed class WebScopedStorageXFileCreationParams + extends PlatformScopedStorageXFileCreationParams { + /// Constructs a [WebScopedStorageXFileCreationParams]. + const WebScopedStorageXFileCreationParams({ + required super.uri, + this.testOverrides, + }); - /// Constructs a [WebXFileCreationParams] with an object url. - factory WebXFileCreationParams.fromObjectUrl({ + /// Constructs a [WebScopedStorageXFileCreationParams] with an object url. + factory WebScopedStorageXFileCreationParams.fromObjectUrl({ required String objectUrl, @visibleForTesting XFileTestOverrides? testOverrides, - }) => UrlWebXFileCreationParams( + }) => UrlWebScopedStorageXFileCreationParams( objectUrl: objectUrl, testOverrides: testOverrides, ); - /// Constructs a [WebXFileCreationParams] with a [Blob]. + /// Constructs a [WebScopedStorageXFileCreationParams] with a [Blob]. /// /// Creates an Object URL using the provided blob. See [URL.createObjectURL] /// /// `autoRevokeObjectUrl`: Whether the unique object url obtained created with /// [blob] should be revoked when this instance is garbage collected. See /// [URL.revokeObjectURL]. - factory WebXFileCreationParams.fromBlob( + factory WebScopedStorageXFileCreationParams.fromBlob( Blob blob, { bool autoRevokeObjectUrl = true, @visibleForTesting XFileTestOverrides? testOverrides, - }) => BlobWebXFileCreationParams( + }) => BlobWebScopedStorageXFileCreationParams( blob, autoRevokeObjectUrl: autoRevokeObjectUrl, testOverrides: testOverrides, @@ -48,21 +52,23 @@ sealed class WebXFileCreationParams extends PlatformXFileCreationParams { final XFileTestOverrides? testOverrides; } -/// Implementation of [WebXFileCreationParams] with an object url. +/// Implementation of [WebScopedStorageXFileCreationParams] with an object url. @immutable -base class UrlWebXFileCreationParams extends WebXFileCreationParams { - /// Constructs a [UrlWebXFileCreationParams]. - const UrlWebXFileCreationParams({ +base class UrlWebScopedStorageXFileCreationParams + extends WebScopedStorageXFileCreationParams { + /// Constructs a [UrlWebScopedStorageXFileCreationParams]. + const UrlWebScopedStorageXFileCreationParams({ required String objectUrl, @visibleForTesting super.testOverrides, }) : super(uri: objectUrl); } -/// Implementation of [WebXFileCreationParams] with a [Blob]. +/// Implementation of [WebScopedStorageXFileCreationParams] with a [Blob]. @immutable -base class BlobWebXFileCreationParams extends WebXFileCreationParams { - /// Constructs a [BlobWebXFileCreationParams]. - BlobWebXFileCreationParams( +base class BlobWebScopedStorageXFileCreationParams + extends WebScopedStorageXFileCreationParams { + /// Constructs a [BlobWebScopedStorageXFileCreationParams]. + BlobWebScopedStorageXFileCreationParams( this.blob, { this.autoRevokeObjectUrl = true, @visibleForTesting super.testOverrides, @@ -76,7 +82,7 @@ base class BlobWebXFileCreationParams extends WebXFileCreationParams { URL.revokeObjectURL(objectUrl); }); - /// The raw data represented by a [WebXFile]. + /// The raw data represented by a [WebScopedStorageXFile]. final Blob blob; /// Whether the object url obtained from [blob] should be revoked when this @@ -84,27 +90,28 @@ base class BlobWebXFileCreationParams extends WebXFileCreationParams { final bool autoRevokeObjectUrl; } -/// Implementation of [PlatformXFile] for web. -base class WebXFile extends PlatformXFile with WebXFileExtension { - /// Constructs a [WebXFile]. - WebXFile(super.params) : super.implementation(); +/// Implementation of [PlatformScopedStorageXFile] for web. +base class WebScopedStorageXFile extends PlatformScopedStorageXFile + with WebScopedStorageXFileExtension { + /// Constructs a [WebScopedStorageXFile]. + WebScopedStorageXFile(super.params) : super.implementation(); Blob? _cachedBlob; @override - PlatformXFileExtension? get extension => this; + PlatformScopedStorageXFileExtension? get extension => this; @override - late final WebXFileCreationParams params = - super.params is WebXFileCreationParams - ? super.params as WebXFileCreationParams - : UrlWebXFileCreationParams(objectUrl: super.params.uri); + late final WebScopedStorageXFileCreationParams params = + super.params is WebScopedStorageXFileCreationParams + ? super.params as WebScopedStorageXFileCreationParams + : UrlWebScopedStorageXFileCreationParams(objectUrl: super.params.uri); @override Future getBlob() async { return _cachedBlob ??= switch (params) { - UrlWebXFileCreationParams() => await fetchBlob(params.uri), - final BlobWebXFileCreationParams params => params.blob, + UrlWebScopedStorageXFileCreationParams() => await fetchBlob(params.uri), + final BlobWebScopedStorageXFileCreationParams params => params.blob, }; } @@ -174,9 +181,10 @@ base class WebXFile extends PlatformXFile with WebXFileExtension { } } -/// Provides platform specific features for [WebXFile]. -mixin WebXFileExtension implements PlatformXFileExtension { - /// The raw data represented by a [WebXFile]. +/// Provides platform specific features for [WebScopedStorageXFile]. +mixin WebScopedStorageXFileExtension + implements PlatformScopedStorageXFileExtension { + /// The raw data represented by a [WebScopedStorageXFile]. Future getBlob(); /// Attempts to download a [Blob], with [suggestedName] as the filename. diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index d64a68bfa51a..fa3b4d693294 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -11,8 +11,8 @@ import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:cross_file_web/cross_file_web.dart'; -import 'package:cross_file_web/src/web_cross_file.dart'; import 'package:cross_file_web/src/web_helpers.dart'; +import 'package:cross_file_web/src/web_scoped_storage_cross_file.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:web/web.dart' as html; @@ -27,53 +27,53 @@ final html.File testFile = html.File( final String testFileUrl = html.URL.createObjectURL(testFile as JSObject); void main() { - group('WebXFile', () { + group('WebScopedStorageXFile', () { CrossFilePlatform.instance = CrossFileWeb(); group('Create with url', () { test('openRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFileUrl), + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), ); expect(await file.openRead().first, testFileBytes); }); test('openRead with partial data', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFileUrl), + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), ); expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); }); test('readAsBytes', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFileUrl), + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), ); expect(await file.readAsBytes(), testFileBytes); }); test('readAsString', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFileUrl), + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), ); expect(await file.readAsString(), testFileStringContents); }); test('canRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFileUrl), + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), ); expect(await file.canRead(), true); }); test('exists', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFileUrl), + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), ); expect(await file.exists(), true); @@ -82,7 +82,9 @@ void main() { group('Create with File', () { test('lastModified', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect( await file.lastModified(), @@ -91,49 +93,65 @@ void main() { }); test('length', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.length(), testFile.size); }); test('openRead', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.openRead().first, testFileBytes); }); test('openRead with partial data', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); }); test('readAsBytes', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.readAsBytes(), testFileBytes); }); test('readAsString', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.readAsString(), testFileStringContents); }); test('canRead', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.canRead(), true); }); test('exists', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.exists(), true); }); test('name', () async { - final file = PlatformXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); expect(await file.name(), testFile.name); }); @@ -144,7 +162,9 @@ void main() { group('XFile download', () { test('creates a DOM container', () async { - final file = WebXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = WebScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); await file.download(''); @@ -156,7 +176,9 @@ void main() { }); test('create anchor element', () async { - final file = WebXFile(WebXFileCreationParams.fromBlob(testFile)); + final file = WebScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); await file.download('path'); @@ -186,8 +208,8 @@ void main() { createAnchorElement: (_, __) => mockAnchor, ); - final file = WebXFile( - WebXFileCreationParams.fromBlob( + final file = WebScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob( testFile, testOverrides: testOverrides, ), From 54d0668d95ebede4de894301337ee3ce1c59108e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:55:16 -0500 Subject: [PATCH 203/398] update darwin --- .../Tests/CrossFileDarwinApiTests.swift | 8 +++ .../CrossFileDarwinApis.g.swift | 42 +++++++------ .../CrossFileDarwinApiImpl.swift | 4 ++ .../cross_file_darwin/example/lib/main.dart | 4 +- .../lib/src/cross_file_darwin_apis.g.dart | 60 ++++++++++++------- .../src/darwin_scoped_storage_cross_file.dart | 4 +- .../pigeons/cross_file_darwin_apis.dart | 3 + ...darwin_scoped_storage_cross_file_test.dart | 32 +++++++--- 8 files changed, 107 insertions(+), 50 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 26451f70e45d..7e4a057016b8 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -48,4 +48,12 @@ struct CrossFileDarwinApiTests { #expect(bookmarkedURLString == testFileURL.absoluteString) } + + @Test func isReadableFile() throws { + let testFileURL = try createTempTestFile() + + let api = CrossFileDarwinApiImpl() + + #expect(try api.isReadableFile(url: testFileURL.absoluteString)) + } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 6718f7f13329..1fad23dcea96 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -67,6 +67,7 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } + private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { } @@ -84,8 +85,7 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec( - readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Api for getting access to file information. @@ -101,23 +101,19 @@ protocol CrossFileDarwinApi { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. func stopAccessingSecurityScopedResource(url: String) throws + /// Whether the native FileManager is able to read a specified file. + func isReadableFile(url: String) throws -> Bool } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp( - binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, - messageChannelSuffix: String = "" - ) { + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -134,10 +130,7 @@ class CrossFileDarwinApiSetup { } /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -154,10 +147,7 @@ class CrossFileDarwinApiSetup { } /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -172,5 +162,21 @@ class CrossFileDarwinApiSetup { } else { stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) } + /// Whether the native FileManager is able to read a specified file. + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + isReadableFileChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let urlArg = args[0] as! String + do { + let result = try api.isReadableFile(url: urlArg) + reply(wrapResult(result)) + } catch { + reply(wrapError(error)) + } + } + } else { + isReadableFileChannel.setMessageHandler(nil) + } } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index f496d0706f5c..7fe4d0853d6f 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -39,4 +39,8 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { func stopAccessingSecurityScopedResource(url: String) throws { URL(string: url)!.stopAccessingSecurityScopedResource() } + + func isReadableFile(url: String) throws -> Bool { + return FileManager.default.isReadableFile(atPath: URL(string: url)!.path) + } } diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 43b332515d93..0fefe2af66c1 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -34,7 +34,9 @@ class FileOpenScreen extends StatelessWidget { case _: debugPrint('File Uri: ${file.uri}'); debugPrint('Filename: $filename'); - debugPrint('Can Read File: ${await file.canRead()}'); + if (file is ScopedStorageXFile) { + debugPrint('Can Read File: ${await file.canRead()}'); + } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 591a0daa863c..dd2537957a05 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -18,6 +18,7 @@ PlatformException _createConnectionError(String channelName) { ); } + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -44,13 +45,9 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({ - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty - ? '.$messageChannelSuffix' - : ''; + CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -60,16 +57,13 @@ class CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -87,16 +81,13 @@ class CrossFileDarwinApi { /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. Future startAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -119,16 +110,13 @@ class CrossFileDarwinApi { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. Future stopAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -142,4 +130,32 @@ class CrossFileDarwinApi { return; } } + + /// Whether the native FileManager is able to read a specified file. + Future isReadableFile(String url) async { + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as bool?)!; + } + } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 0c726ceee330..31ec2b4a42c0 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -85,7 +85,9 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile _file.readAsString(encoding: encoding); @override - Future canRead() => exists(); + Future canRead() { + return params.api.isReadableFile(params.uri); + } @override Future exists() async => _file.existsSync(); diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index 1184477e8be3..5f0374b12357 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -28,4 +28,7 @@ abstract class CrossFileDarwinApi { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. void stopAccessingSecurityScopedResource(String url); + + /// Whether the native FileManager is able to read a specified file. + bool isReadableFile(String url); } diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index b3222eee9a8d..eff0b1b6abb4 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -28,49 +28,65 @@ void main() { }); test('lastModified', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.lastModified(), testFile.lastModifiedSync()); }); test('length', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.length(), await testFile.length()); }); test('openRead', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.openRead().toList(), await testFile.openRead().toList()); }); test('readAsBytes', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.readAsBytes(), await testFile.readAsBytes()); }); test('readAsString', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.readAsString(), await testFile.readAsString()); }); test('canRead', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.canRead(), testFile.existsSync()); }); test('exists', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.exists(), testFile.existsSync()); }); test('name', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.path)); + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.path), + ); expect(await file.name(), 'test_file.txt'); }); From b276f77de765c61fd452d995b9348200bc6c2e84 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:56:21 -0500 Subject: [PATCH 204/398] update android --- packages/cross_file/cross_file_android/example/lib/main.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index d4afa2abd81b..a9744626b099 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -42,7 +42,9 @@ class FileOpenScreen extends StatelessWidget { case _: debugPrint('File Uri: ${file.uri}'); debugPrint('Filename: $filename'); - debugPrint('Can Read File: ${await file.canRead()}'); + if (file is ScopedStorageXFile) { + debugPrint('Can Read File: ${await file.canRead()}'); + } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; From 9eeb9ed1103fdef8481fbfb94e581bc573b14d3f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:58:01 -0500 Subject: [PATCH 205/398] update io --- packages/cross_file/cross_file_io/example/lib/main.dart | 1 - .../cross_file/cross_file_io/lib/src/io_cross_file.dart | 3 --- .../cross_file/cross_file_io/test/io_cross_file_test.dart | 8 -------- 3 files changed, 12 deletions(-) diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart index 29b1369ba4da..da54acf95606 100644 --- a/packages/cross_file/cross_file_io/example/lib/main.dart +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -34,7 +34,6 @@ class FileOpenScreen extends StatelessWidget { case _: debugPrint('File Uri: ${file.uri}'); debugPrint('Filename: $filename'); - debugPrint('Can Read File: ${await file.canRead()}'); debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 8857bce6b68a..5e3b80de26bc 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -76,9 +76,6 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { Future readAsString({Encoding encoding = utf8}) => file.readAsString(encoding: encoding); - @override - Future canRead() => exists(); - @override Future exists() async => file.existsSync(); diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index 33087c169933..66ad88661596 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -62,14 +62,6 @@ void main() { expect(await file.readAsString(), await testFile.readAsString()); }); - test('canRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), - ); - - expect(await file.canRead(), testFile.existsSync()); - }); - test('exists', () async { final file = PlatformXFile( PlatformXFileCreationParams(uri: testFile.path), From ac3dcf0dfcf71c404ef91f1b19fd25a7b4426fa5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:03:40 -0500 Subject: [PATCH 206/398] update cross_file --- .../cross_file/cross_file/example/lib/main.dart | 4 +++- .../cross_file/example/lib/readme_excerpts.dart | 4 ++-- .../cross_file/cross_file/lib/src/cross_file.dart | 3 --- .../lib/src/scoped_storage_cross_file.dart | 3 +++ .../cross_file/cross_file/test/cross_file_test.dart | 12 ------------ .../test/scoped_storage_cross_file_test.dart | 13 +++++++++++++ .../cross_file_web/lib/cross_file_web.dart | 7 ++++++- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index 29b1369ba4da..0a9282069d3c 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -34,7 +34,9 @@ class FileOpenScreen extends StatelessWidget { case _: debugPrint('File Uri: ${file.uri}'); debugPrint('Filename: $filename'); - debugPrint('Can Read File: ${await file.canRead()}'); + if (file is ScopedStorageXFile) { + debugPrint('Can Read File: ${await file.canRead()}'); + } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 677a2998065c..e85111e13767 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -20,7 +20,7 @@ Future instantiateXFile() async { debugPrint('- URI: ${file.uri}'); debugPrint('- Name: ${await file.name()}'); - if (await file.canRead()) { + if (await file.exists()) { final String fileContent = await file.readAsString(); debugPrint('Content of the file: $fileContent'); } @@ -35,7 +35,7 @@ Future accessPlatformFeatures() async { late final XFile file; if (CrossFilePlatform.instance is CrossFileWeb) { - final params = WebXFileCreationParams.fromObjectUrl( + final params = WebScopedStorageXFileCreationParams.fromObjectUrl( objectUrl: 'blob:https://some/url:for/file', ); file = XFile.fromCreationParams(params); diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index a4213fc405b1..36eedb983489 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -96,9 +96,6 @@ class XFile extends XFileEntity { /// Returns null if the information is not available. Future length() => platform.length(); - /// Whether the resource represented by this reference can be read. - Future canRead() => platform.canRead(); - /// Creates a new independent Stream for the contents of this resource. /// /// If start is present, the file will be read from byte-offset start. diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 7ffe675f5828..f84ef6610478 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -79,4 +79,7 @@ class ScopedStorageXFile extends XFile { @override PlatformScopedStorageXFile get platform => super.platform as PlatformScopedStorageXFile; + + /// Whether the resource represented by this reference can be read. + Future canRead() => platform.canRead(); } diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart index 94aed4f5f023..a81caa9c4a0d 100644 --- a/packages/cross_file/cross_file/test/cross_file_test.dart +++ b/packages/cross_file/cross_file/test/cross_file_test.dart @@ -78,18 +78,6 @@ void main() { expect(await file.readAsString(), message); }); - test('canRead', () async { - const canRead = false; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onCanRead: () async => canRead), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.canRead(), canRead); - }); - test('exists', () async { const exists = true; CrossFilePlatform.instance = TestCrossFilePlatform( diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart index dbb729be6fc6..2d65d4081807 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart @@ -131,5 +131,18 @@ void main() { expect(await file.name(), name); }); + + test('canRead', () async { + const canRead = false; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: + (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onCanRead: () async => canRead), + ); + + final file = ScopedStorageXFile(uri: 'uri'); + + expect(await file.canRead(), canRead); + }); }); } diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 6785103cd2fb..bc43417d8ec6 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -3,7 +3,12 @@ // found in the LICENSE file. export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show CrossFilePlatform, PlatformXFileCreationParams; + show + CrossFilePlatform, + ListParams, + PlatformScopedStorageXDirectoryCreationParams, + PlatformScopedStorageXFileCreationParams, + PlatformXFileEntity; export 'src/cross_file_web.dart'; export 'src/web_scoped_storage_cross_file.dart' From ae1f8e06d440da66563dde870f8800f383f63380 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:08:56 -0500 Subject: [PATCH 207/398] format and excerpts --- packages/cross_file/cross_file/README.md | 4 +- .../CrossFileDarwinApis.g.swift | 29 ++++++++++---- .../lib/src/cross_file_darwin_apis.g.dart | 39 +++++++++++++------ 3 files changed, 51 insertions(+), 21 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index 3b44c02fc1b3..ee7c8a597540 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -28,7 +28,7 @@ debugPrint('File information:'); debugPrint('- URI: ${file.uri}'); debugPrint('- Name: ${await file.name()}'); -if (await file.canRead()) { +if (await file.exists()) { final String fileContent = await file.readAsString(); debugPrint('Content of the file: $fileContent'); } @@ -76,7 +76,7 @@ Below is an example of using additional iOS/macOS and Web features for a `XFile` late final XFile file; if (CrossFilePlatform.instance is CrossFileWeb) { - final params = WebXFileCreationParams.fromObjectUrl( + final params = WebScopedStorageXFileCreationParams.fromObjectUrl( objectUrl: 'blob:https://some/url:for/file', ); file = XFile.fromCreationParams(params); diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 1fad23dcea96..aaafd8fa12e8 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -67,7 +67,6 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } - private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { } @@ -85,7 +84,8 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Api for getting access to file information. @@ -109,11 +109,17 @@ protocol CrossFileDarwinApi { class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { + static func setUp( + binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, + messageChannelSuffix: String = "" + ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -130,7 +136,10 @@ class CrossFileDarwinApiSetup { } /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -147,7 +156,10 @@ class CrossFileDarwinApiSetup { } /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -163,7 +175,10 @@ class CrossFileDarwinApiSetup { stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) } /// Whether the native FileManager is able to read a specified file. - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let isReadableFileChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index dd2537957a05..c2414e831d9c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -18,7 +18,6 @@ PlatformException _createConnectionError(String channelName) { ); } - class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -45,9 +44,13 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; + CrossFileDarwinApi({ + BinaryMessenger? binaryMessenger, + String messageChannelSuffix = '', + }) : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty + ? '.$messageChannelSuffix' + : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -57,13 +60,16 @@ class CrossFileDarwinApi { /// Attempt to create a bookmarked URL that serves as a persistent reference /// to a file. Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -81,13 +87,16 @@ class CrossFileDarwinApi { /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. Future startAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -110,13 +119,16 @@ class CrossFileDarwinApi { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. Future stopAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -133,13 +145,16 @@ class CrossFileDarwinApi { /// Whether the native FileManager is able to read a specified file. Future isReadableFile(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [url], + ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); From bae2e4d92bf6343e1257e4edb78d9a1cc8ef117b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:37:30 -0500 Subject: [PATCH 208/398] fix darwin tests --- .../darwin_scoped_storage_cross_directory_test.dart | 4 ++-- ...win_scoped_storage_cross_directory_test.mocks.dart | 8 ++++++++ .../test/darwin_scoped_storage_cross_file_test.dart | 11 ++++++++--- .../darwin_scoped_storage_cross_file_test.mocks.dart | 8 ++++++++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart index da01217c8625..255608d4962f 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -36,8 +36,8 @@ void main() { }); test('list', () async { - final directory = PlatformXDirectory( - PlatformXDirectoryCreationParams(uri: testDirectory.path), + final directory = PlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.path), ); expect( diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart index 95079740d0fd..4ec12cc13aa4 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart @@ -68,4 +68,12 @@ class MockCrossFileDarwinApi extends _i1.Mock returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + + @override + _i4.Future isReadableFile(String? url) => + (super.noSuchMethod( + Invocation.method(#isReadableFile, [url]), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); } diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index eff0b1b6abb4..a30bd7d08d8c 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -68,11 +68,16 @@ void main() { }); test('canRead', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const result = true; + when(mockApi.isReadableFile(uri)).thenAnswer((_) async => result); + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), ); - expect(await file.canRead(), testFile.existsSync()); + expect(await file.canRead(), result); }); test('exists', () async { diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart index 5806deaa1dea..3d780ae3a264 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart @@ -68,4 +68,12 @@ class MockCrossFileDarwinApi extends _i1.Mock returnValueForMissingStub: _i4.Future.value(), ) as _i4.Future); + + @override + _i4.Future isReadableFile(String? url) => + (super.noSuchMethod( + Invocation.method(#isReadableFile, [url]), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); } From 6ec9c3fb10024a41673f4499a5e41f944d1e9429 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:49:29 -0500 Subject: [PATCH 209/398] update darwin and io to maybe run on windows --- ...n_scoped_storage_cross_directory_test.dart | 20 ++++++++++------ ...darwin_scoped_storage_cross_file_test.dart | 24 ++++++++++--------- .../test/io_cross_directory_test.dart | 4 ++-- .../test/io_cross_file_test.dart | 14 +++++------ 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart index 255608d4962f..602a055a332d 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -28,8 +28,10 @@ void main() { }); test('exists', () async { - final directory = PlatformXDirectory( - PlatformXDirectoryCreationParams(uri: testDirectory.path), + final directory = PlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams( + uri: testDirectory.uri.toString(), + ), ); expect(await directory.exists(), testDirectory.existsSync()); @@ -37,7 +39,9 @@ void main() { test('list', () async { final directory = PlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.path), + PlatformScopedStorageXDirectoryCreationParams( + uri: testDirectory.uri.toString(), + ), ); expect( @@ -52,7 +56,7 @@ void main() { test('startAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri/'; + final uri = testDirectory.uri.toString(); const result = true; when( mockApi.startAccessingSecurityScopedResource(uri), @@ -67,7 +71,7 @@ void main() { test('stopAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri/'; + final uri = testDirectory.uri.toString(); final file = DarwinScopedStorageXDirectory( DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), @@ -79,8 +83,10 @@ void main() { test('tryCreateBookmarkedUrl', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri/'; - const bookmarkedUri = 'newUri/'; + final uri = testDirectory.uri.toString(); + final bookmarkedUri = Directory( + path.join(Directory.current.path, 'someDirectory'), + ).uri.toString(); when( mockApi.tryCreateBookmarkedUrl(uri), ).thenAnswer((_) async => bookmarkedUri); diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index a30bd7d08d8c..52f4301618a4 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -29,7 +29,7 @@ void main() { test('lastModified', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.lastModified(), testFile.lastModifiedSync()); @@ -37,7 +37,7 @@ void main() { test('length', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.length(), await testFile.length()); @@ -45,7 +45,7 @@ void main() { test('openRead', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.openRead().toList(), await testFile.openRead().toList()); @@ -53,7 +53,7 @@ void main() { test('readAsBytes', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.readAsBytes(), await testFile.readAsBytes()); @@ -61,7 +61,7 @@ void main() { test('readAsString', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.readAsString(), await testFile.readAsString()); @@ -82,7 +82,7 @@ void main() { test('exists', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.exists(), testFile.existsSync()); @@ -90,7 +90,7 @@ void main() { test('name', () async { final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.path), + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.name(), 'test_file.txt'); @@ -98,7 +98,7 @@ void main() { test('startAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; + final uri = testFile.uri.toString(); const result = true; when( mockApi.startAccessingSecurityScopedResource(uri), @@ -113,7 +113,7 @@ void main() { test('stopAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; + final uri = testFile.uri.toString(); final file = DarwinScopedStorageXFile( DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), @@ -125,8 +125,10 @@ void main() { test('tryCreateBookmarkedUrl', () async { final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const bookmarkedUri = 'newUri'; + final uri = testFile.uri.toString(); + final bookmarkedUri = File( + path.join(Directory.current.path, 'some', 'file.txt'), + ).uri.toString(); when( mockApi.tryCreateBookmarkedUrl(uri), ).thenAnswer((_) async => bookmarkedUri); diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart index 94ae20734561..62b7ee4a815d 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -21,7 +21,7 @@ void main() { test('exists', () async { final directory = PlatformXDirectory( - PlatformXDirectoryCreationParams(uri: testDirectory.path), + PlatformXDirectoryCreationParams(uri: testDirectory.uri.toString()), ); expect(await directory.exists(), testDirectory.existsSync()); @@ -29,7 +29,7 @@ void main() { test('list', () async { final directory = PlatformXDirectory( - PlatformXDirectoryCreationParams(uri: testDirectory.path), + PlatformXDirectoryCreationParams(uri: testDirectory.uri.toString()), ); expect( diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index 66ad88661596..a57190e5ea3f 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -21,7 +21,7 @@ void main() { test('lastModified', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.lastModified(), testFile.lastModifiedSync()); @@ -29,7 +29,7 @@ void main() { test('length', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.length(), await testFile.length()); @@ -37,7 +37,7 @@ void main() { test('openRead', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect( @@ -48,7 +48,7 @@ void main() { test('readAsBytes', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.readAsBytes(), await testFile.readAsBytes()); @@ -56,7 +56,7 @@ void main() { test('readAsString', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.readAsString(), await testFile.readAsString()); @@ -64,7 +64,7 @@ void main() { test('exists', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.exists(), testFile.existsSync()); @@ -72,7 +72,7 @@ void main() { test('name', () async { final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.path), + PlatformXFileCreationParams(uri: testFile.uri.toString()), ); expect(await file.name(), 'test_file.txt'); From 15f311e6d81bef4db42cb3e5f262fac4a8e74b9a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:52:24 -0500 Subject: [PATCH 210/398] add convenience method for cross_File --- .../cross_file/cross_file/lib/src/cross_directory.dart | 3 +++ packages/cross_file/cross_file/lib/src/cross_file.dart | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 636b7f2d781c..e94a22108ea4 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -47,6 +47,9 @@ class XDirectory extends XFileEntity { /// platform. XDirectory.fromUri(Uri uri) : this(uri: uri.toString()); + /// Constructs a [XDirectory] from a path. + XDirectory.fromPath(String path) : this.fromUri(Uri.directory(path)); + /// Constructs a [XDirectory] from creation params for a specific platform. /// /// {@template cross_file.XDirectory.fromCreationParams} diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 36eedb983489..d9772782e39a 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -38,12 +38,12 @@ class XFile extends XFileEntity { XFile({required String uri}) : this.fromCreationParams(PlatformXFileCreationParams(uri: uri)); - /// Constructs a [XFile]. - /// - /// See [XFile.fromCreationParams] for setting parameters for a specific - /// platform. + /// Constructs a [XFile] from a [Uri]. XFile.fromUri(Uri uri) : this(uri: uri.toString()); + /// Constructs a [XFile] from a file path. + XFile.fromPath(String path) : this.fromUri(Uri.file(path)); + /// Constructs a [XFile] from creation params for a specific platform. /// /// {@template cross_file.XFile.fromCreationParams} From b4799e8541f038ded9f7570a82432d4947aa074e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 14:23:12 -0500 Subject: [PATCH 211/398] remove android integration endpoint --- .../cross_file/cross_file_android/example/lib/main.dart | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index a9744626b099..0a9282069d3c 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -4,16 +4,8 @@ import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_driver/driver_extension.dart'; import 'package:mime/mime.dart' as mime; -/// Entry point for integration tests that require espresso. -@pragma('vm:entry-point') -void integrationTestMain() { - enableFlutterDriverExtension(); - main(); -} - void main() { runApp(const MaterialApp(home: FileOpenScreen())); } From a04ebd49fe2023f27412f4e2123743751a6c3abe Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 14:47:17 -0500 Subject: [PATCH 212/398] update baseline --- .../cross_file_android/android/build.gradle | 1 + .../android/lint-baseline.xml | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 packages/cross_file/cross_file_android/android/lint-baseline.xml diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle index 76be940e7a67..478762ccca42 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle +++ b/packages/cross_file/cross_file_android/android/build.gradle @@ -61,6 +61,7 @@ android { checkAllWarnings = true warningsAsErrors = true disable 'AndroidGradlePluginVersion', 'InvalidPackage', 'GradleDependency', 'NewerVersionAvailable' + baseline = file("lint-baseline.xml") } testOptions { diff --git a/packages/cross_file/cross_file_android/android/lint-baseline.xml b/packages/cross_file/cross_file_android/android/lint-baseline.xml new file mode 100644 index 000000000000..31b083d26319 --- /dev/null +++ b/packages/cross_file/cross_file_android/android/lint-baseline.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + From 920bb3130f5ccedfd10f86c7cb8a453143724eb1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 14:54:39 -0500 Subject: [PATCH 213/398] delete old test --- .../example/ios/RunnerTests/RunnerTests.swift | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift deleted file mode 100644 index 1e018c094ec5..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/RunnerTests.swift +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Testing -import UIKit - -@testable import cross_file_darwin - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -struct RunnerTests { - @Test func testGetPlatform() { - #expect(true == true) - } -} From f19b74e5fe0c12a065acf58d4b0f9d3c41edc96b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:31:15 -0500 Subject: [PATCH 214/398] remove can read from xfile --- packages/cross_file/cross_file/test/test_stubs.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 69337b87fb86..5a397b2395ce 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -64,7 +64,6 @@ final class TestCrossFilePlatform extends CrossFilePlatform { final class TestXFile extends PlatformXFile { TestXFile( super.params, { - this.onCanRead, this.onExists, this.onLastModified, this.onLength, @@ -74,7 +73,6 @@ final class TestXFile extends PlatformXFile { this.onReadAsString, }) : super.implementation(); - Future Function()? onCanRead; Future Function()? onExists; Future Function()? onLastModified; Future Function()? onLength; @@ -83,11 +81,6 @@ final class TestXFile extends PlatformXFile { Future Function()? onReadAsBytes; Future Function({required Encoding encoding})? onReadAsString; - @override - Future canRead() async { - return await onCanRead?.call() ?? false; - } - @override Future exists() async { return await onExists?.call() ?? false; From f01d4bd82334740df35039e3b729698ce4511c49 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:12:57 -0500 Subject: [PATCH 215/398] remove old pubspec and example --- packages/cross_file/example/pubspec.yaml | 18 ------------------ packages/cross_file/pubspec.yaml | 19 ------------------- 2 files changed, 37 deletions(-) delete mode 100644 packages/cross_file/example/pubspec.yaml delete mode 100644 packages/cross_file/pubspec.yaml diff --git a/packages/cross_file/example/pubspec.yaml b/packages/cross_file/example/pubspec.yaml deleted file mode 100644 index 591212e013ca..000000000000 --- a/packages/cross_file/example/pubspec.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: cross_file_example -description: Demonstrates how to use cross files. -publish_to: none - -environment: - sdk: ^3.9.0 - -dependencies: - cross_file: - # When depending on this package from a real application you should use: - # cross_file: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ - -dev_dependencies: - test: ^1.24.0 diff --git a/packages/cross_file/pubspec.yaml b/packages/cross_file/pubspec.yaml deleted file mode 100644 index b8cdbf1719c5..000000000000 --- a/packages/cross_file/pubspec.yaml +++ /dev/null @@ -1,19 +0,0 @@ -name: cross_file -description: An abstraction to allow working with files across multiple platforms. -repository: https://github.com/flutter/packages/tree/main/packages/cross_file -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.3.5+2 - -environment: - sdk: ^3.9.0 - -dependencies: - meta: ^1.3.0 - web: ">=0.5.1 <2.0.0" - -dev_dependencies: - path: ^1.8.1 - test: ^1.21.1 - -topics: - - files From 9ca64a774a801cc2acf6421d21dd56f5a21f084c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 17 Feb 2026 18:02:47 -0500 Subject: [PATCH 216/398] remove runner tests --- .../example/ios/Runner.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 3a080bfd2891..80520570a3a1 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -9,7 +9,6 @@ /* Begin PBXBuildFile section */ 0BBE3A77F94E5BCEF9021C5A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; @@ -49,7 +48,6 @@ 26C8F5E7A3000CE8EAEBCE2D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; @@ -95,7 +93,6 @@ isa = PBXGroup; children = ( 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */, - 331C807B294A618700263BE5 /* RunnerTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -314,10 +311,14 @@ inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); + inputPaths = ( + ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); + outputPaths = ( + ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; @@ -374,7 +375,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From b70935c853b919cac28c7cdf9c4a4f8bf8dadb72 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 18 Feb 2026 13:54:53 -0500 Subject: [PATCH 217/398] remove bookmark uri logic --- .../Tests/CrossFileDarwinApiTests.swift | 9 ------- .../CrossFileDarwinApis.g.swift | 23 ---------------- .../CrossFileDarwinApiImpl.swift | 18 ------------- .../lib/src/cross_file_darwin_apis.g.dart | 27 ------------------- ...darwin_scoped_storage_cross_directory.dart | 5 ---- .../src/darwin_scoped_storage_cross_file.dart | 5 ---- .../lib/src/security_scoped_resource.dart | 7 ----- .../pigeons/cross_file_darwin_apis.dart | 4 --- ...n_scoped_storage_cross_directory_test.dart | 17 ------------ ...ed_storage_cross_directory_test.mocks.dart | 8 ------ ...darwin_scoped_storage_cross_file_test.dart | 17 ------------ ..._scoped_storage_cross_file_test.mocks.dart | 8 ------ 12 files changed, 148 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift index 7e4a057016b8..c556fcb2e62f 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift @@ -40,15 +40,6 @@ struct CrossFileDarwinApiTests { #expect(try String(contentsOf: testFileURL, encoding: .utf8) == "Hello, World!") } - @Test func tryCreateBookmarkedUrl() throws { - let testFileURL = try createTempTestFile() - - let api = CrossFileDarwinApiImpl() - let bookmarkedURLString = try! api.tryCreateBookmarkedUrl(url: testFileURL.absoluteString)! - - #expect(bookmarkedURLString == testFileURL.absoluteString) - } - @Test func isReadableFile() throws { let testFileURL = try createTempTestFile() diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index aaafd8fa12e8..539e2eb56909 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -92,9 +92,6 @@ class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Se /// /// Generated protocol from Pigeon that represents a handler of messages from Flutter. protocol CrossFileDarwinApi { - /// Attempt to create a bookmarked URL that serves as a persistent reference - /// to a file. - func tryCreateBookmarkedUrl(url: String) throws -> String? /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. func startAccessingSecurityScopedResource(url: String) throws -> Bool @@ -114,26 +111,6 @@ class CrossFileDarwinApiSetup { messageChannelSuffix: String = "" ) { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - /// Attempt to create a bookmarked URL that serves as a persistent reference - /// to a file. - let tryCreateBookmarkedUrlChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - tryCreateBookmarkedUrlChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.tryCreateBookmarkedUrl(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - tryCreateBookmarkedUrlChannel.setMessageHandler(nil) - } /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 7fe4d0853d6f..7c394045cbd0 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -14,24 +14,6 @@ import Foundation /// Implementation of `CrossFileDarwinApi`. class CrossFileDarwinApiImpl: CrossFileDarwinApi { - func tryCreateBookmarkedUrl(url: String) throws -> String? { - let nativeUrl = URL(string: url)! - let data = try nativeUrl.bookmarkData( - options: [], - includingResourceValuesForKeys: nil, - relativeTo: nil - ) - - var isStale: Bool = true - let bookmarkedUrl: URL = try URL(resolvingBookmarkData: data, bookmarkDataIsStale: &isStale) - - if !isStale { - return bookmarkedUrl.absoluteString - } - - return nil - } - func startAccessingSecurityScopedResource(url: String) throws -> Bool { return URL(string: url)!.startAccessingSecurityScopedResource() } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index c2414e831d9c..68ff99b92971 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -57,33 +57,6 @@ class CrossFileDarwinApi { final String pigeonVar_messageChannelSuffix; - /// Attempt to create a bookmarked URL that serves as a persistent reference - /// to a file. - Future tryCreateBookmarkedUrl(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.tryCreateBookmarkedUrl$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return (pigeonVar_replyList[0] as String?); - } - } - /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. Future startAccessingSecurityScopedResource(String url) async { diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index fe459c923cd5..3690eebda288 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -89,11 +89,6 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory Future stopAccessingSecurityScopedResource() { return params.api.stopAccessingSecurityScopedResource(params.uri); } - - @override - Future toBookmarkedUri() async { - return params.api.tryCreateBookmarkedUrl(params.uri); - } } /// Provides platform specific features for [DarwinScopedStorageXDirectory]. diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 31ec2b4a42c0..59aefa82096a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -104,11 +104,6 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile Future stopAccessingSecurityScopedResource() { return params.api.stopAccessingSecurityScopedResource(params.uri); } - - @override - Future toBookmarkedUri() async { - return params.api.tryCreateBookmarkedUrl(params.uri); - } } /// Provides platform specific features for [DarwinScopedStorageXFile]. diff --git a/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart b/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart index c9bb5543665e..66b3aa632e83 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/security_scoped_resource.dart @@ -11,11 +11,4 @@ mixin SecurityScopedResource { /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. Future stopAccessingSecurityScopedResource(); - - /// Attempt to create a bookmarked URI that serves as a persistent reference - /// to the resource. - /// - /// Throws exception if the file could not be bookmarked or null if the - /// bookmark is stale. - Future toBookmarkedUri(); } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index 5f0374b12357..f181ee9742cf 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -17,10 +17,6 @@ import 'package:pigeon/pigeon.dart'; /// Api for getting access to file information. @HostApi() abstract class CrossFileDarwinApi { - /// Attempt to create a bookmarked URL that serves as a persistent reference - /// to a file. - String? tryCreateBookmarkedUrl(String url); - /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. bool startAccessingSecurityScopedResource(String url); diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart index 602a055a332d..aa32d59f42d0 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -80,21 +80,4 @@ void main() { await file.stopAccessingSecurityScopedResource(); verify(mockApi.stopAccessingSecurityScopedResource(uri)); }); - - test('tryCreateBookmarkedUrl', () async { - final mockApi = MockCrossFileDarwinApi(); - final uri = testDirectory.uri.toString(); - final bookmarkedUri = Directory( - path.join(Directory.current.path, 'someDirectory'), - ).uri.toString(); - when( - mockApi.tryCreateBookmarkedUrl(uri), - ).thenAnswer((_) async => bookmarkedUri); - - final file = DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.toBookmarkedUri(), bookmarkedUri); - }); } diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart index 4ec12cc13aa4..de0293c07512 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart @@ -44,14 +44,6 @@ class MockCrossFileDarwinApi extends _i1.Mock ) as String); - @override - _i4.Future tryCreateBookmarkedUrl(String? url) => - (super.noSuchMethod( - Invocation.method(#tryCreateBookmarkedUrl, [url]), - returnValue: _i4.Future.value(), - ) - as _i4.Future); - @override _i4.Future startAccessingSecurityScopedResource(String? url) => (super.noSuchMethod( diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index 52f4301618a4..1dd0d30ae8ec 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -122,21 +122,4 @@ void main() { await file.stopAccessingSecurityScopedResource(); verify(mockApi.stopAccessingSecurityScopedResource(uri)); }); - - test('tryCreateBookmarkedUrl', () async { - final mockApi = MockCrossFileDarwinApi(); - final uri = testFile.uri.toString(); - final bookmarkedUri = File( - path.join(Directory.current.path, 'some', 'file.txt'), - ).uri.toString(); - when( - mockApi.tryCreateBookmarkedUrl(uri), - ).thenAnswer((_) async => bookmarkedUri); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.toBookmarkedUri(), bookmarkedUri); - }); } diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart index 3d780ae3a264..1706ee616334 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart @@ -44,14 +44,6 @@ class MockCrossFileDarwinApi extends _i1.Mock ) as String); - @override - _i4.Future tryCreateBookmarkedUrl(String? url) => - (super.noSuchMethod( - Invocation.method(#tryCreateBookmarkedUrl, [url]), - returnValue: _i4.Future.value(), - ) - as _i4.Future); - @override _i4.Future startAccessingSecurityScopedResource(String? url) => (super.noSuchMethod( From a0c2fd4611d7fe69a7f8653f5b0dc1daa27f8ac8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:04:52 -0500 Subject: [PATCH 218/398] add config --- .ci/scripts/prepare_tool.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.ci/scripts/prepare_tool.sh b/.ci/scripts/prepare_tool.sh index 33646d56e7cd..21d60b74f6d8 100755 --- a/.ci/scripts/prepare_tool.sh +++ b/.ci/scripts/prepare_tool.sh @@ -8,5 +8,8 @@ set -e git fetch origin main git branch main origin/main +# Enables long paths to work on Windows. +git config --system core.longpaths true + cd script/tool dart pub get From e4d1d26ff1540cd6cc7c67554a7492a1405884bd Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 25 Feb 2026 16:59:23 -0500 Subject: [PATCH 219/398] try global --- .ci/scripts/prepare_tool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/scripts/prepare_tool.sh b/.ci/scripts/prepare_tool.sh index 21d60b74f6d8..af1d0e99d7d4 100755 --- a/.ci/scripts/prepare_tool.sh +++ b/.ci/scripts/prepare_tool.sh @@ -9,7 +9,7 @@ git fetch origin main git branch main origin/main # Enables long paths to work on Windows. -git config --system core.longpaths true +git config --global core.longpaths true cd script/tool dart pub get From 28b16790ec2d79061b42423bf8f9d99f5630d1b6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 27 Feb 2026 16:59:47 -0500 Subject: [PATCH 220/398] missing apostrophe --- .../scoped_storage/platform_scoped_storage_cross_directory.dart | 2 +- .../src/scoped_storage/platform_scoped_storage_cross_file.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index bdeec05e45fd..9b6fdc0d3f7c 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -68,7 +68,7 @@ base class PlatformScopedStorageXDirectoryCreationParams mixin PlatformScopedStorageXDirectoryExtension implements PlatformXDirectoryExtension {} -/// A reference to a directory (or folder) on the file system within a devices +/// A reference to a directory (or folder) on the file system within a device's /// scoped storage. abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { /// Creates a new [PlatformScopedStorageXDirectory] diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index f35774771860..8a7c5d38bd58 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -67,7 +67,7 @@ base class PlatformScopedStorageXFileCreationParams /// ``` mixin PlatformScopedStorageXFileExtension implements PlatformXFileExtension {} -/// Interface for a reference to a local data resource within a devices +/// Interface for a reference to a local data resource within a device's /// scoped storage. abstract base class PlatformScopedStorageXFile extends PlatformXFile { /// Creates a new [PlatformScopedStorageXFile] From d845bcbf949c7e72200d55d75d5e2a6d9d92476b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 2 Mar 2026 14:29:16 -0500 Subject: [PATCH 221/398] update platform xdirectory --- .../lib/src/platform_cross_directory.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 87804e76c967..cc945fbd7062 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -69,7 +69,7 @@ base class PlatformXDirectoryCreationParams /// ``` mixin PlatformXDirectoryExtension implements PlatformXFileEntityExtension {} -/// A reference to a directory (or folder) on the file system. +/// Interface for a reference to a directory (or folder) on the file system. abstract base class PlatformXDirectory extends PlatformXFileEntity { /// Creates a new [PlatformXDirectory]. factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { From 574eb1aeb6671db54fb2b4fe2698a0b925a93887 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:22:45 -0400 Subject: [PATCH 222/398] update gradles to kotlins --- .../example/android/app/build.gradle | 68 ------------------- .../example/android/app/build.gradle.kts | 50 ++++++++++++++ .../cross_file/example/android/build.gradle | 24 ------- .../example/android/build.gradle.kts | 33 +++++++++ .../example/android/settings.gradle | 27 -------- .../example/android/settings.gradle.kts | 28 ++++++++ .../{build.gradle => build.gradle.kts} | 47 +++++++------ .../android/settings.gradle | 1 - .../android/settings.gradle.kts | 1 + .../example/android/app/build.gradle | 68 ------------------- .../example/android/app/build.gradle.kts | 49 +++++++++++++ .../example/android/build.gradle | 39 ----------- .../example/android/build.gradle.kts | 45 ++++++++++++ .../example/android/settings.gradle | 28 -------- .../example/android/settings.gradle.kts | 28 ++++++++ 15 files changed, 259 insertions(+), 277 deletions(-) delete mode 100644 packages/cross_file/cross_file/example/android/app/build.gradle create mode 100644 packages/cross_file/cross_file/example/android/app/build.gradle.kts delete mode 100644 packages/cross_file/cross_file/example/android/build.gradle create mode 100644 packages/cross_file/cross_file/example/android/build.gradle.kts delete mode 100644 packages/cross_file/cross_file/example/android/settings.gradle create mode 100644 packages/cross_file/cross_file/example/android/settings.gradle.kts rename packages/cross_file/cross_file_android/android/{build.gradle => build.gradle.kts} (62%) delete mode 100644 packages/cross_file/cross_file_android/android/settings.gradle create mode 100644 packages/cross_file/cross_file_android/android/settings.gradle.kts delete mode 100644 packages/cross_file/cross_file_android/example/android/app/build.gradle create mode 100644 packages/cross_file/cross_file_android/example/android/app/build.gradle.kts delete mode 100644 packages/cross_file/cross_file_android/example/android/build.gradle create mode 100644 packages/cross_file/cross_file_android/example/android/build.gradle.kts delete mode 100644 packages/cross_file/cross_file_android/example/android/settings.gradle create mode 100644 packages/cross_file/cross_file_android/example/android/settings.gradle.kts diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle b/packages/cross_file/cross_file/example/android/app/build.gradle deleted file mode 100644 index d1a654b282e9..000000000000 --- a/packages/cross_file/cross_file/example/android/app/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - namespace = "dev.flutter.packages.cross_file_example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - applicationId "dev.flutter.packages.cross_file_example" - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = '../..' -} - -dependencies { - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test:runner:1.2.0") - androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") - api("androidx.test:core:1.4.0") -} diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle.kts b/packages/cross_file/cross_file/example/android/app/build.gradle.kts new file mode 100644 index 000000000000..b8f95097948d --- /dev/null +++ b/packages/cross_file/cross_file/example/android/app/build.gradle.kts @@ -0,0 +1,50 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "dev.flutter.packages.cross_file_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + applicationId = "dev.flutter.packages.cross_file_example" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + signingConfig = signingConfigs.getByName("debug") + } + } + lint { + disable.add("InvalidPackage") + } +} + +flutter { + source = "../.." +} + +dependencies { + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test:runner:1.2.0") + androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") + api("androidx.test:core:1.4.0") +} + diff --git a/packages/cross_file/cross_file/example/android/build.gradle b/packages/cross_file/cross_file/example/android/build.gradle deleted file mode 100644 index b9db5700753a..000000000000 --- a/packages/cross_file/cross_file/example/android/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -allprojects { - repositories { - // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. - def artifactRepoKey = 'ARTIFACT_HUB_REPOSITORY' - if (System.getenv().containsKey(artifactRepoKey)) { - println "Using artifact hub" - maven { url System.getenv(artifactRepoKey) } - } - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} diff --git a/packages/cross_file/cross_file/example/android/build.gradle.kts b/packages/cross_file/cross_file/example/android/build.gradle.kts new file mode 100644 index 000000000000..a8bde37d0c72 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/build.gradle.kts @@ -0,0 +1,33 @@ +allprojects { + repositories { + // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. + val artifactRepoKey = "ARTIFACT_HUB_REPOSITORY" + val artifactRepoUrl = System.getenv(artifactRepoKey) + if (artifactRepoUrl != null) { + println("Using artifact hub") + maven { + url = uri(artifactRepoUrl) + } + } + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/packages/cross_file/cross_file/example/android/settings.gradle b/packages/cross_file/cross_file/example/android/settings.gradle deleted file mode 100644 index 96fce46479f8..000000000000 --- a/packages/cross_file/cross_file/example/android/settings.gradle +++ /dev/null @@ -1,27 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -// See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.11.0" apply false - id "org.jetbrains.kotlin.android" version "2.2.0" apply false - id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.1" -} - -include ":app" diff --git a/packages/cross_file/cross_file/example/android/settings.gradle.kts b/packages/cross_file/cross_file/example/android/settings.gradle.kts new file mode 100644 index 000000000000..e3993757c096 --- /dev/null +++ b/packages/cross_file/cross_file/example/android/settings.gradle.kts @@ -0,0 +1,28 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +// See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false + id("com.google.cloud.artifactregistry.gradle-plugin") version "2.2.1" +} + +include(":app") diff --git a/packages/cross_file/cross_file_android/android/build.gradle b/packages/cross_file/cross_file_android/android/build.gradle.kts similarity index 62% rename from packages/cross_file/cross_file_android/android/build.gradle rename to packages/cross_file/cross_file_android/android/build.gradle.kts index 478762ccca42..5782a2a65844 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle +++ b/packages/cross_file/cross_file_android/android/build.gradle.kts @@ -1,8 +1,10 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + group = "dev.flutter.packages.cross_file_android" version = "1.0" buildscript { - ext.kotlin_version = "2.3.0" + val kotlinVersion = "2.3.0" repositories { google() mavenCentral() @@ -10,7 +12,7 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle:8.13.1") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } } @@ -21,8 +23,16 @@ allprojects { } } -apply plugin: "com.android.library" -apply plugin: "kotlin-android" +plugins { + id("com.android.library") + id("kotlin-android") +} + +kotlin { + compilerOptions { + jvmTarget = JvmTarget.fromTarget(JavaVersion.VERSION_17.toString()) + } +} android { namespace = "dev.flutter.packages.cross_file_android" @@ -33,17 +43,9 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - sourceSets { - main.java.srcDirs += "src/main/kotlin" - test.java.srcDirs += "src/test/kotlin" - } - defaultConfig { minSdk = 24 + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } dependencies { @@ -60,19 +62,20 @@ android { lint { checkAllWarnings = true warningsAsErrors = true - disable 'AndroidGradlePluginVersion', 'InvalidPackage', 'GradleDependency', 'NewerVersionAvailable' + disable.addAll(setOf("AndroidGradlePluginVersion", "InvalidPackage", "GradleDependency", "NewerVersionAvailable")) baseline = file("lint-baseline.xml") } testOptions { - unitTests.includeAndroidResources = true - unitTests.returnDefaultValues = true - unitTests.all { - useJUnitPlatform() - testLogging { - events "passed", "skipped", "failed", "standardOut", "standardError" - outputs.upToDateWhen {false} - showStandardStreams = true + unitTests { + isIncludeAndroidResources = true + isReturnDefaultValues = true + all { + it.outputs.upToDateWhen { false } + it.testLogging { + events("passed", "skipped", "failed", "standardOut", "standardError") + showStandardStreams = true + } } } } diff --git a/packages/cross_file/cross_file_android/android/settings.gradle b/packages/cross_file/cross_file_android/android/settings.gradle deleted file mode 100644 index 3800a971764d..000000000000 --- a/packages/cross_file/cross_file_android/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'cross_file_android' diff --git a/packages/cross_file/cross_file_android/android/settings.gradle.kts b/packages/cross_file/cross_file_android/android/settings.gradle.kts new file mode 100644 index 000000000000..ee402190e51c --- /dev/null +++ b/packages/cross_file/cross_file_android/android/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "cross_file_android" diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle b/packages/cross_file/cross_file_android/example/android/app/build.gradle deleted file mode 100644 index fbe0ce9a9178..000000000000 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle +++ /dev/null @@ -1,68 +0,0 @@ -plugins { - id "com.android.application" - id "kotlin-android" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - namespace = "dev.flutter.packages.cross_file_android_example" - compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - defaultConfig { - applicationId "dev.flutter.packages.cross_file_android_example" - minSdk = flutter.minSdkVersion - targetSdk = flutter.targetSdkVersion - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - signingConfig = signingConfigs.debug - } - } -} - -flutter { - source = '../..' -} - -dependencies { - testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test:runner:1.2.0") - androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") - api("androidx.test:core:1.4.0") -} diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts new file mode 100644 index 000000000000..a08966429556 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + id("com.android.application") + id("kotlin-android") + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "dev.flutter.packages.cross_file_android_example" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + applicationId = "dev.flutter.packages.cross_file_android_example" + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + signingConfig = signingConfigs.getByName("debug") + } + } + lint { + disable.add("InvalidPackage") + } +} + +flutter { + source = "../.." +} + +dependencies { + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test:runner:1.2.0") + androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") + api("androidx.test:core:1.4.0") +} diff --git a/packages/cross_file/cross_file_android/example/android/build.gradle b/packages/cross_file/cross_file_android/example/android/build.gradle deleted file mode 100644 index 988fd1c987e9..000000000000 --- a/packages/cross_file/cross_file_android/example/android/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} - -allprojects { - repositories { - // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. - def artifactRepoKey = 'ARTIFACT_HUB_REPOSITORY' - if (System.getenv().containsKey(artifactRepoKey)) { - println "Using artifact hub" - maven { url System.getenv(artifactRepoKey) } - } - google() - mavenCentral() - } -} - -gradle.projectsEvaluated { - project(":cross_file_android") { - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:all" << "-Werror" - } - } -} diff --git a/packages/cross_file/cross_file_android/example/android/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/build.gradle.kts new file mode 100644 index 000000000000..ec52edfd8d36 --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/build.gradle.kts @@ -0,0 +1,45 @@ +allprojects { + repositories { + // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. + val artifactRepoKey = "ARTIFACT_HUB_REPOSITORY" + val artifactRepoUrl = System.getenv(artifactRepoKey) + if (artifactRepoUrl != null) { + println("Using artifact hub") + maven { + url = uri(artifactRepoUrl) + } + } + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} + +// Build the plugin project with warnings enabled. This is here rather than +// in the plugin itself to avoid breaking clients that have different +// warnings (e.g., deprecation warnings from a newer SDK than this project +// builds with). +gradle.projectsEvaluated { + project(":cross_file_android") { + tasks.withType { + options.compilerArgs.addAll(listOf("-Xlint:all", "-Werror")) + } + } +} diff --git a/packages/cross_file/cross_file_android/example/android/settings.gradle b/packages/cross_file/cross_file_android/example/android/settings.gradle deleted file mode 100644 index 56cb7f02e493..000000000000 --- a/packages/cross_file/cross_file_android/example/android/settings.gradle +++ /dev/null @@ -1,28 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -// See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.11.0" apply false - id "org.jetbrains.kotlin.android" version "2.2.0" apply false - id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.1" -} - -include ":app" - diff --git a/packages/cross_file/cross_file_android/example/android/settings.gradle.kts b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts new file mode 100644 index 000000000000..a0118892641d --- /dev/null +++ b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts @@ -0,0 +1,28 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +// See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false + id("com.google.cloud.artifactregistry.gradle-plugin") version "2.2.1" +} + +include(":app") From a0169fb6ce9e1de42e68fde9d74beff64c9e1573 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:31:31 -0400 Subject: [PATCH 223/398] add a test --- .../integration_test/cross_file_test.dart | 25 ++++++++++++++++--- .../cross_file/example/pubspec.yaml | 7 ++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart index 621977be68c7..1d8e0da114ce 100644 --- a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -2,13 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + +import 'package:cross_file/cross_file.dart'; +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - // Since this test is lacking integration tests, this test ensures the example - // app can be launched on an emulator/device. - testWidgets('Launch Test', (WidgetTester tester) async {}); + testWidgets('Can read from file using dart:io implementation', ( + WidgetTester tester, + ) async { + final Directory dir = await getTemporaryDirectory(); + + final xDir = XDirectory.fromPath(dir.path); + expect(await xDir.exists(), isTrue); + + final file = XFile.fromPath(path.join(dir.path, 'hello.txt')); + file.getExtension().file + ..createSync() + ..writeAsStringSync('Hello, World!'); + + expect(await file.readAsString(), 'Hello, World!'); + }, skip: kIsWeb); } diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index c6c82bb4cc80..e0a15ac8da48 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -22,6 +22,11 @@ dependencies: url: https://github.com/bparrishMines/packages ref: new_crossfile path: packages/cross_file/cross_file_darwin + cross_file_io: + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_io cross_file_web: git: url: https://github.com/bparrishMines/packages @@ -42,6 +47,8 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + path: ^1.9.1 + path_provider: ^2.1.5 flutter: uses-material-design: true From 340c4620ea745e2265863f6e419f5f7e9a31830c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:33:08 -0400 Subject: [PATCH 224/398] remove generated files --- .../linux/flutter/generated_plugins.cmake | 23 ------------------- .../windows/flutter/generated_plugins.cmake | 23 ------------------- 2 files changed, 46 deletions(-) delete mode 100644 packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake delete mode 100644 packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake diff --git a/packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake b/packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 2e1de87a7eb6..000000000000 --- a/packages/cross_file/cross_file/example/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake b/packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake deleted file mode 100644 index b93c4c30c167..000000000000 --- a/packages/cross_file/cross_file/example/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) From a1a621c987a7ff4d6144cb2cd8786ce36562372e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:33:42 -0400 Subject: [PATCH 225/398] remove generated files --- .../linux/flutter/generated_plugins.cmake | 23 ------------------- .../windows/flutter/generated_plugins.cmake | 23 ------------------- 2 files changed, 46 deletions(-) delete mode 100644 packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake delete mode 100644 packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake diff --git a/packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake b/packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake deleted file mode 100644 index 2e1de87a7eb6..000000000000 --- a/packages/cross_file/cross_file_io/example/linux/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) diff --git a/packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake b/packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake deleted file mode 100644 index b93c4c30c167..000000000000 --- a/packages/cross_file/cross_file_io/example/windows/flutter/generated_plugins.cmake +++ /dev/null @@ -1,23 +0,0 @@ -# -# Generated file, do not edit. -# - -list(APPEND FLUTTER_PLUGIN_LIST -) - -list(APPEND FLUTTER_FFI_PLUGIN_LIST -) - -set(PLUGIN_BUNDLED_LIBRARIES) - -foreach(plugin ${FLUTTER_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) - target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) - list(APPEND PLUGIN_BUNDLED_LIBRARIES $) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) -endforeach(plugin) - -foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) - add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) - list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) -endforeach(ffi_plugin) From 7c2ad195fb08eded1b70463e5e4848fcf47f0ef6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:38:37 -0400 Subject: [PATCH 226/398] update project --- .../ios/Runner.xcodeproj/project.pbxproj | 55 +++++++++---------- .../xcshareddata/xcschemes/Runner.xcscheme | 18 ++++++ .../macos/Runner.xcodeproj/project.pbxproj | 46 ++++++++-------- .../xcshareddata/xcschemes/Runner.xcscheme | 18 ++++++ 4 files changed, 86 insertions(+), 51 deletions(-) diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj index c6bc1f30ab8d..4630c2dc33d7 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ @@ -11,11 +11,11 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 9D5ABF2BFD3F5F3216E37BDF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */; }; - C7741C8FE1202DC4D2942D67 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4F576F2A577117482CBAA056 /* Pods_RunnerTests.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,15 +44,15 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = RunnerTests.xctest; path = "/Users/bmparr/Development/packages/packages/cross_file/cross_file/example/ios/build/Debug-iphoneos/Runner.app/PlugIns/RunnerTests.xctest"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 4F576F2A577117482CBAA056 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 725B8D3BB6CDC5144FD4E5B7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; @@ -72,6 +72,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, 9D5ABF2BFD3F5F3216E37BDF /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -80,7 +81,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C7741C8FE1202DC4D2942D67 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -90,6 +90,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -113,7 +114,6 @@ isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, - 331C8081294A63A400263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -138,7 +138,6 @@ isa = PBXGroup; children = ( 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */, - 4F576F2A577117482CBAA056 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -189,13 +188,15 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 9050369081B08E0B437C3785 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -229,6 +230,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -321,27 +325,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 9050369081B08E0B437C3785 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -721,6 +704,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index e3773d42e24c..c3fedb29c990 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + + + + + + + + + + + Date: Tue, 21 Apr 2026 11:50:57 -0400 Subject: [PATCH 227/398] remove ref --- .../example/macos/Runner.xcodeproj/project.pbxproj | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj index 7d7d4c950e7e..a7949e178d7b 100644 --- a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXAggregateTarget section */ @@ -21,7 +21,6 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 223056F6078A0B29F9794331 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 13AF930B762038462526C125 /* Pods_RunnerTests.framework */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -62,9 +61,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 13AF930B762038462526C125 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1791B30977A096C697D5C0C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = RunnerTests.xctest; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file/example/macos/build/Debug/cross_file_example.app/Contents/PlugIns/RunnerTests.xctest; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* cross_file_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cross_file_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -95,7 +93,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 223056F6078A0B29F9794331 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -137,7 +134,6 @@ isa = PBXGroup; children = ( 33CC10ED2044A3C60003C045 /* cross_file_example.app */, - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, ); name = Products; sourceTree = ""; @@ -195,7 +191,6 @@ isa = PBXGroup; children = ( FD409983E262F02D75B6545E /* Pods_Runner.framework */, - 13AF930B762038462526C125 /* Pods_RunnerTests.framework */, ); name = Frameworks; sourceTree = ""; @@ -287,7 +282,7 @@ ); mainGroup = 33CC10E42044A3C60003C045; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; @@ -777,7 +772,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; From bb8b14902e7cd3e4f52d3c06c1c3ae63bdda575c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:58:12 -0400 Subject: [PATCH 228/398] remove pods --- .../cross_file/cross_file/example/README.md | 10 +- .../cross_file/cross_file/example/ios/Podfile | 43 ------ .../ios/Runner.xcodeproj/project.pbxproj | 77 +---------- .../cross_file/example/macos/Podfile | 42 ------ .../macos/Runner.xcodeproj/project.pbxproj | 77 +---------- .../cross_file_darwin/example/ios/Podfile | 43 ------ .../ios/Runner.xcodeproj/project.pbxproj | 123 ++++-------------- .../xcshareddata/xcschemes/Runner.xcscheme | 18 +++ .../cross_file_darwin/example/macos/Podfile | 42 ------ .../macos/Runner.xcodeproj/project.pbxproj | 119 ++++------------- .../xcshareddata/xcschemes/Runner.xcscheme | 18 +++ 11 files changed, 90 insertions(+), 522 deletions(-) delete mode 100644 packages/cross_file/cross_file/example/ios/Podfile delete mode 100644 packages/cross_file/cross_file/example/macos/Podfile delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/Podfile delete mode 100644 packages/cross_file/cross_file_darwin/example/macos/Podfile diff --git a/packages/cross_file/cross_file/example/README.md b/packages/cross_file/cross_file/example/README.md index 96b8bb17dbff..ebcc1b46869b 100644 --- a/packages/cross_file/cross_file/example/README.md +++ b/packages/cross_file/cross_file/example/README.md @@ -1,9 +1,3 @@ -# Platform Implementation Test App +# cross_file_example -This is a test app for manual testing and automated integration testing -of this platform implementation. It is not intended to demonstrate actual use of -this package, since the intent is that plugin clients use the app-facing -package. - -Unless you are making changes to this implementation package, this example is -very unlikely to be relevant. +Demonstrates how to use the cross_file plugin. \ No newline at end of file diff --git a/packages/cross_file/cross_file/example/ios/Podfile b/packages/cross_file/cross_file/example/ios/Podfile deleted file mode 100644 index 620e46eba607..000000000000 --- a/packages/cross_file/cross_file/example/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj index 4630c2dc33d7..fca44f7a3211 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; - 9D5ABF2BFD3F5F3216E37BDF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -46,9 +45,6 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = RunnerTests.xctest; path = "/Users/bmparr/Development/packages/packages/cross_file/cross_file/example/ios/build/Debug-iphoneos/Runner.app/PlugIns/RunnerTests.xctest"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 725B8D3BB6CDC5144FD4E5B7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -61,10 +57,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - A008FDEFE186795A9B02CB4F /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - A5578CFEE2C8B362F29ECF39 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - DB861370BF100AD4A286A356 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,7 +65,6 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - 9D5ABF2BFD3F5F3216E37BDF /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -106,7 +97,6 @@ 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, C6869AEB60FAA8D6CEE6FA87 /* Pods */, - 9F5AF9B51C64E38CA0A7E19F /* Frameworks */, ); sourceTree = ""; }; @@ -134,23 +124,9 @@ path = Runner; sourceTree = ""; }; - 9F5AF9B51C64E38CA0A7E19F /* Frameworks */ = { - isa = PBXGroup; - children = ( - 504968999090CEE6BD5E6AC4 /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; C6869AEB60FAA8D6CEE6FA87 /* Pods */ = { isa = PBXGroup; children = ( - 725B8D3BB6CDC5144FD4E5B7 /* Pods-Runner.debug.xcconfig */, - A008FDEFE186795A9B02CB4F /* Pods-Runner.release.xcconfig */, - A5578CFEE2C8B362F29ECF39 /* Pods-Runner.profile.xcconfig */, - DB861370BF100AD4A286A356 /* Pods-RunnerTests.debug.xcconfig */, - 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */, - FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -162,7 +138,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 7D383C8584CA0BAB73229DC3 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, E42B53E4B6191CE70EE6A051 /* Frameworks */, @@ -181,7 +156,6 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 81428E1333C25AFC5945A7F4 /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -231,7 +205,7 @@ ); mainGroup = 97C146E51CF9000F007C117D; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; @@ -281,50 +255,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 7D383C8584CA0BAB73229DC3 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 81428E1333C25AFC5945A7F4 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -466,7 +396,6 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DB861370BF100AD4A286A356 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -484,7 +413,6 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4C3E3EE98AFDD7AD2C241987 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -500,7 +428,6 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FC3B6166344B1B39C67DF648 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -706,7 +633,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/packages/cross_file/cross_file/example/macos/Podfile b/packages/cross_file/cross_file/example/macos/Podfile deleted file mode 100644 index ff5ddb3b8bdc..000000000000 --- a/packages/cross_file/cross_file/example/macos/Podfile +++ /dev/null @@ -1,42 +0,0 @@ -platform :osx, '10.15' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj index a7949e178d7b..6cc8657cdc96 100644 --- a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj @@ -27,7 +27,6 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - CDCABB3C5E47BFDA2D2D1F97 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD409983E262F02D75B6545E /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -61,7 +60,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 1791B30977A096C697D5C0C4 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = RunnerTests.xctest; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file/example/macos/build/Debug/cross_file_example.app/Contents/PlugIns/RunnerTests.xctest; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; @@ -77,15 +75,9 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 437F33A43BFDC4B887DE8BDA /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 51890A064A97BBBEC5098087 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; - B63E82A3F401053BCA32C3C4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - FD409983E262F02D75B6545E /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,7 +93,6 @@ buildActionMask = 2147483647; files = ( 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, - CDCABB3C5E47BFDA2D2D1F97 /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -125,7 +116,6 @@ 33FAB671232836740065AC1E /* Runner */, 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, 3DE641040F107AF7D132DC0F /* Pods */, ); sourceTree = ""; @@ -177,24 +167,10 @@ 3DE641040F107AF7D132DC0F /* Pods */ = { isa = PBXGroup; children = ( - B63E82A3F401053BCA32C3C4 /* Pods-Runner.debug.xcconfig */, - 51890A064A97BBBEC5098087 /* Pods-Runner.release.xcconfig */, - 1791B30977A096C697D5C0C4 /* Pods-Runner.profile.xcconfig */, - 437F33A43BFDC4B887DE8BDA /* Pods-RunnerTests.debug.xcconfig */, - A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */, - AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - FD409983E262F02D75B6545E /* Pods_Runner.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -202,7 +178,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - C46F10307CFD10DE28500907 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -221,7 +196,6 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 254EC0B0D434ADEDBB256DFD /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, @@ -282,7 +256,7 @@ ); mainGroup = 33CC10E42044A3C60003C045; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; @@ -315,28 +289,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 254EC0B0D434ADEDBB256DFD /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -375,28 +327,6 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - C46F10307CFD10DE28500907 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -447,7 +377,6 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 437F33A43BFDC4B887DE8BDA /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -462,7 +391,6 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = A8EF8F3FBFE0FFF37E4022DC /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -477,7 +405,6 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AC12149C65C95C1AE1180FD1 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -772,7 +699,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/packages/cross_file/cross_file_darwin/example/ios/Podfile b/packages/cross_file/cross_file_darwin/example/ios/Podfile deleted file mode 100644 index 620e46eba607..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/Podfile +++ /dev/null @@ -1,43 +0,0 @@ -# Uncomment this line to define a global platform for your project -# platform :ios, '13.0' - -# CocoaPods analytics sends network stats synchronously affecting flutter build latency. -ENV['COCOAPODS_DISABLE_STATS'] = 'true' - -project 'Runner', { - 'Debug' => :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_ios_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_ios_build_settings(target) - end -end diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 80520570a3a1..d24f2c2f5f5e 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -7,12 +7,11 @@ objects = { /* Begin PBXBuildFile section */ - 0BBE3A77F94E5BCEF9021C5A /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; - 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; @@ -45,18 +44,14 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 26C8F5E7A3000CE8EAEBCE2D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; - 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; - 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -64,9 +59,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9D1864A39D740B0EAEC60CD5 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - B8A1290F753E9B94CB42B68A /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; - BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -74,7 +66,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0BBE3A77F94E5BCEF9021C5A /* Pods_Runner.framework in Frameworks */, + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -82,7 +74,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 87E2BFE282CB477A431CF7DF /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -97,18 +88,10 @@ path = RunnerTests; sourceTree = ""; }; - 6F98F75533BE3213F9C0BF8F /* Frameworks */ = { - isa = PBXGroup; - children = ( - BC6C9B7340FA95FE4267AE7F /* Pods_Runner.framework */, - 9602D2B4619B7A716C4C80D1 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -125,7 +108,6 @@ 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, DB75EE80F48401E65664EBB7 /* Pods */, - 6F98F75533BE3213F9C0BF8F /* Frameworks */, ); sourceTree = ""; }; @@ -157,12 +139,6 @@ DB75EE80F48401E65664EBB7 /* Pods */ = { isa = PBXGroup; children = ( - B8A1290F753E9B94CB42B68A /* Pods-Runner.debug.xcconfig */, - 7CF818CFA5FB20A8AC1467CD /* Pods-Runner.release.xcconfig */, - 26C8F5E7A3000CE8EAEBCE2D /* Pods-Runner.profile.xcconfig */, - 9D1864A39D740B0EAEC60CD5 /* Pods-RunnerTests.debug.xcconfig */, - 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */, - 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -174,7 +150,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - B10C59BD6BC2E3B30B458863 /* [CP] Check Pods Manifest.lock */, 331C807D294A63A400263BE5 /* Sources */, 331C807F294A63A400263BE5 /* Resources */, B320E567E4FD783B390DDCB2 /* Frameworks */, @@ -193,20 +168,21 @@ isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - E0527587EB0D03F15D75982F /* [CP] Check Pods Manifest.lock */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 9CD0C6A1D95F083343210EC4 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -240,6 +216,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -303,71 +282,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - 9CD0C6A1D95F083343210EC4 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - inputPaths = ( - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - B10C59BD6BC2E3B30B458863 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - E0527587EB0D03F15D75982F /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -495,7 +409,6 @@ }; 331C8088294A63A400263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 9D1864A39D740B0EAEC60CD5 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -514,7 +427,6 @@ }; 331C8089294A63A400263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 2F59C6F87154F8240EF20DCF /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -530,7 +442,6 @@ }; 331C808A294A63A400263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3082B90ADC21503FE3B2C8E8 /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; @@ -734,6 +645,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index e3773d42e24c..c3fedb29c990 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + :debug, - 'Profile' => :release, - 'Release' => :release, -} - -def flutter_root - generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) - unless File.exist?(generated_xcode_build_settings_path) - raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" - end - - File.foreach(generated_xcode_build_settings_path) do |line| - matches = line.match(/FLUTTER_ROOT\=(.*)/) - return matches[1].strip if matches - end - raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" -end - -require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) - -flutter_macos_podfile_setup - -target 'Runner' do - use_frameworks! - - flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) - target 'RunnerTests' do - inherit! :search_paths - end -end - -post_install do |installer| - installer.pods_project.targets.each do |target| - flutter_additional_macos_build_settings(target) - end -end diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index 735b9856137d..1b6877440d11 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,14 +21,13 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 1E3F930A949E6BF1A392A157 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 8FB3B0B92F3D820100A1CEDF /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */; }; - 9365FDE22965FC1D9207E2E0 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63A129979C19E770A95C46BB /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -62,7 +61,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; @@ -78,16 +76,10 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 63A129979C19E770A95C46BB /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 68E94AA7D5658C9B4705BC78 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; - 6E84AA1E5316F40ABCA87AF9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; - 7255794ECF94B4FB91F39D79 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; - 95E600C17773E34356453E89 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -95,7 +87,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1E3F930A949E6BF1A392A157 /* Pods_RunnerTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -103,7 +94,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 9365FDE22965FC1D9207E2E0 /* Pods_Runner.framework in Frameworks */, + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -136,7 +127,6 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 331C80D6294CF71000263BE5 /* RunnerTests */, 33CC10EE2044A3C60003C045 /* Products */, - D73912EC22F37F3D000D13A0 /* Frameworks */, 91814838E1B0599FEE23D945 /* Pods */, ); sourceTree = ""; @@ -164,6 +154,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, @@ -188,25 +179,10 @@ 91814838E1B0599FEE23D945 /* Pods */ = { isa = PBXGroup; children = ( - 95E600C17773E34356453E89 /* Pods-Runner.debug.xcconfig */, - 7255794ECF94B4FB91F39D79 /* Pods-Runner.release.xcconfig */, - 6E84AA1E5316F40ABCA87AF9 /* Pods-Runner.profile.xcconfig */, - 68E94AA7D5658C9B4705BC78 /* Pods-RunnerTests.debug.xcconfig */, - AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */, - 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */, ); path = Pods; sourceTree = ""; }; - D73912EC22F37F3D000D13A0 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 63A129979C19E770A95C46BB /* Pods_Runner.framework */, - 542EA9A2F3AFEE0208F79BB1 /* Pods_RunnerTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -214,7 +190,6 @@ isa = PBXNativeTarget; buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildPhases = ( - 249AA0E568CF9FDCD7843723 /* [CP] Check Pods Manifest.lock */, 331C80D1294CF70F00263BE5 /* Sources */, 331C80D2294CF70F00263BE5 /* Frameworks */, 331C80D3294CF70F00263BE5 /* Resources */, @@ -233,13 +208,11 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - D807BD7D820175A61286FA90 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - 610737436CA1CAF7E249AF7E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -247,6 +220,9 @@ 33CC11202044C79F0003C045 /* PBXTargetDependency */, ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 33CC10ED2044A3C60003C045 /* cross_file_darwin_example.app */; productType = "com.apple.product-type.application"; @@ -291,6 +267,9 @@ Base, ); mainGroup = 33CC10E42044A3C60003C045; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -322,28 +301,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 249AA0E568CF9FDCD7843723 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -382,45 +339,6 @@ shellPath = /bin/sh; shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 610737436CA1CAF7E249AF7E /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - D807BD7D820175A61286FA90 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -472,7 +390,6 @@ /* Begin XCBuildConfiguration section */ 331C80DB294CF71000263BE5 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 68E94AA7D5658C9B4705BC78 /* Pods-RunnerTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -487,7 +404,6 @@ }; 331C80DC294CF71000263BE5 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = AF56CD661CE6FC3643B381E8 /* Pods-RunnerTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -502,7 +418,6 @@ }; 331C80DD294CF71000263BE5 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 1CB2823D6DE86B76A18195DA /* Pods-RunnerTests.profile.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CURRENT_PROJECT_VERSION = 1; @@ -795,6 +710,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 33CC10E52044A3C60003C045 /* Project object */; } diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index af474038da98..5ed213de499d 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -5,6 +5,24 @@ + + + + + + + + + + Date: Tue, 21 Apr 2026 12:27:59 -0400 Subject: [PATCH 229/398] remove runnertests refernces --- .../ios/Runner.xcodeproj/project.pbxproj | 77 ------------------- .../macos/Runner.xcodeproj/project.pbxproj | 72 ----------------- 2 files changed, 149 deletions(-) diff --git a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj index fca44f7a3211..79c1e490b8e6 100644 --- a/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/ios/Runner.xcodeproj/project.pbxproj @@ -43,7 +43,6 @@ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = RunnerTests.xctest; path = "/Users/bmparr/Development/packages/packages/cross_file/cross_file/example/ios/build/Debug-iphoneos/Runner.app/PlugIns/RunnerTests.xctest"; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -134,24 +133,6 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 331C8080294A63A400263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C807D294A63A400263BE5 /* Sources */, - 331C807F294A63A400263BE5 /* Resources */, - E42B53E4B6191CE70EE6A051 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - 331C8086294A63A400263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; @@ -212,7 +193,6 @@ projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, - 331C8080294A63A400263BE5 /* RunnerTests */, ); }; /* End PBXProject section */ @@ -394,53 +374,6 @@ }; name = Profile; }; - 331C8088294A63A400263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Debug; - }; - 331C8089294A63A400263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Release; - }; - 331C808A294A63A400263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; - }; - name = Profile; - }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -600,16 +533,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C8088294A63A400263BE5 /* Debug */, - 331C8089294A63A400263BE5 /* Release */, - 331C808A294A63A400263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj index 6cc8657cdc96..c2a9ac645ffa 100644 --- a/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file/example/macos/Runner.xcodeproj/project.pbxproj @@ -60,7 +60,6 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; name = RunnerTests.xctest; path = /Users/bmparr/Development/packages/packages/cross_file/cross_file/example/macos/build/Debug/cross_file_example.app/Contents/PlugIns/RunnerTests.xctest; sourceTree = ""; }; 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; 33CC10ED2044A3C60003C045 /* cross_file_example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = cross_file_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -174,24 +173,6 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 331C80D4294CF70F00263BE5 /* RunnerTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; - buildPhases = ( - 331C80D1294CF70F00263BE5 /* Sources */, - 331C80D2294CF70F00263BE5 /* Frameworks */, - 331C80D3294CF70F00263BE5 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 331C80DA294CF71000263BE5 /* PBXTargetDependency */, - ); - name = RunnerTests; - productName = RunnerTests; - productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 33CC10EC2044A3C60003C045 /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; @@ -263,7 +244,6 @@ projectRoot = ""; targets = ( 33CC10EC2044A3C60003C045 /* Runner */, - 331C80D4294CF70F00263BE5 /* RunnerTests */, 33CC111A2044C6BA0003C045 /* Flutter Assemble */, ); }; @@ -375,48 +355,6 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 331C80DB294CF71000263BE5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_example"; - }; - name = Debug; - }; - 331C80DC294CF71000263BE5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_example"; - }; - name = Release; - }; - 331C80DD294CF71000263BE5 /* Profile */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CURRENT_PROJECT_VERSION = 1; - GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileExample.RunnerTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_example"; - }; - name = Profile; - }; 338D0CE9231458BD00FA5F75 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; @@ -656,16 +594,6 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 331C80DB294CF71000263BE5 /* Debug */, - 331C80DC294CF71000263BE5 /* Release */, - 331C80DD294CF71000263BE5 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( From ef0b7fc1cc992c6816b1be318d6afa3ccdb2ec4a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:21:22 -0400 Subject: [PATCH 230/398] add a is current implementation --- .../cross_file/cross_file_android/lib/cross_file_android.dart | 1 - .../cross_file_android/lib/src/cross_file_android.dart | 4 ++++ .../cross_file/cross_file_darwin/lib/cross_file_darwin.dart | 1 - .../cross_file_darwin/lib/src/cross_file_darwin.dart | 4 ++++ packages/cross_file/cross_file_io/lib/cross_file_io.dart | 1 - packages/cross_file/cross_file_io/lib/src/cross_file_io.dart | 4 ++++ packages/cross_file/cross_file_web/lib/cross_file_web.dart | 1 - .../cross_file/cross_file_web/lib/src/cross_file_web.dart | 4 ++++ 8 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index dbf0a9f3f0b0..dc71ec375c41 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -4,7 +4,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - CrossFilePlatform, ListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index b3b6c47a5017..e57ab7ade60d 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -15,6 +15,10 @@ base class CrossFileAndroid extends CrossFileIO { CrossFilePlatform.instance = CrossFileAndroid(); } + /// Whether the current implementation of `cross_file` is [CrossFileAndroid]. + static bool isCurrentImplementation() => + CrossFilePlatform.instance.runtimeType == CrossFileAndroid; + @override AndroidScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index ddc7700c87b6..b9979adee001 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -4,7 +4,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - CrossFilePlatform, ListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index f00f2dc02852..e68261025156 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -15,6 +15,10 @@ base class CrossFileDarwin extends CrossFileIO { CrossFilePlatform.instance = CrossFileDarwin(); } + /// Whether the current implementation of `cross_file` is [CrossFileDarwin]. + static bool isCurrentImplementation() => + CrossFilePlatform.instance.runtimeType == CrossFileDarwin; + @override DarwinScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 7ce95334bd36..9fd4cfeb7f6b 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -4,7 +4,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - CrossFilePlatform, ListParams, PlatformXDirectoryCreationParams, PlatformXFileCreationParams, diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index 4382dbce0a9e..bf0368a28397 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -14,6 +14,10 @@ base class CrossFileIO extends CrossFilePlatform { CrossFilePlatform.instance = CrossFileIO(); } + /// Whether the current implementation of `cross_file` is [CrossFileIO]. + static bool isCurrentImplementation() => + CrossFilePlatform.instance.runtimeType == CrossFileIO; + @override IOXFile createPlatformXFile(PlatformXFileCreationParams params) { return IOXFile(params); diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index bc43417d8ec6..2aaceef7f335 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -4,7 +4,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - CrossFilePlatform, ListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart index 5559639b05c3..cfbac22cfe1f 100644 --- a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -14,6 +14,10 @@ base class CrossFileWeb extends CrossFilePlatform { CrossFilePlatform.instance = CrossFileWeb(); } + /// Whether the current implementation of `cross_file` is [CrossFileWeb]. + static bool isCurrentImplementation() => + CrossFilePlatform.instance.runtimeType == CrossFileWeb; + @override WebScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, From 410469300b860313729655bdf998fa19c051b397 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:24:28 -0400 Subject: [PATCH 231/398] update exerpts --- packages/cross_file/cross_file/README.md | 4 ++-- .../cross_file/cross_file/example/lib/readme_excerpts.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index ee7c8a597540..5111a212be8e 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -75,12 +75,12 @@ Below is an example of using additional iOS/macOS and Web features for a `XFile` ```dart late final XFile file; -if (CrossFilePlatform.instance is CrossFileWeb) { +if (CrossFileWeb.isCurrentImplementation()) { final params = WebScopedStorageXFileCreationParams.fromObjectUrl( objectUrl: 'blob:https://some/url:for/file', ); file = XFile.fromCreationParams(params); -} else if (CrossFilePlatform.instance is CrossFileDarwin) { +} else if (CrossFileDarwin.isCurrentImplementation()) { file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); await file diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index e85111e13767..0a16a3598511 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -34,12 +34,12 @@ Future accessPlatformFeatures() async { // #docregion platform_features late final XFile file; - if (CrossFilePlatform.instance is CrossFileWeb) { + if (CrossFileWeb.isCurrentImplementation()) { final params = WebScopedStorageXFileCreationParams.fromObjectUrl( objectUrl: 'blob:https://some/url:for/file', ); file = XFile.fromCreationParams(params); - } else if (CrossFilePlatform.instance is CrossFileDarwin) { + } else if (CrossFileDarwin.isCurrentImplementation()) { file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); await file From b4a47f40a57acdfbb17811533b0d2d4cf0b32d21 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:27:56 -0400 Subject: [PATCH 232/398] change to use maybe get extension --- packages/cross_file/cross_file/README.md | 9 +++++---- .../cross_file/example/lib/readme_excerpts.dart | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index 5111a212be8e..d696df3364cc 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -82,15 +82,16 @@ if (CrossFileWeb.isCurrentImplementation()) { file = XFile.fromCreationParams(params); } else if (CrossFileDarwin.isCurrentImplementation()) { file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); - - await file - .getExtension() - .startAccessingSecurityScopedResource(); } else { file = XFile.fromUri(Uri.file('/my/file.txt')); } +await file + .maybeGetExtension() + ?.startAccessingSecurityScopedResource(); + debugPrint(await file.readAsString()); + await file .maybeGetExtension() ?.stopAccessingSecurityScopedResource(); diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 0a16a3598511..a558486ca627 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -41,15 +41,16 @@ Future accessPlatformFeatures() async { file = XFile.fromCreationParams(params); } else if (CrossFileDarwin.isCurrentImplementation()) { file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); - - await file - .getExtension() - .startAccessingSecurityScopedResource(); } else { file = XFile.fromUri(Uri.file('/my/file.txt')); } + await file + .maybeGetExtension() + ?.startAccessingSecurityScopedResource(); + debugPrint(await file.readAsString()); + await file .maybeGetExtension() ?.stopAccessingSecurityScopedResource(); From 58678a4f49dabc5ab7b843888b70f18d08d22552 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:34:46 -0400 Subject: [PATCH 233/398] add comment --- packages/cross_file/cross_file/lib/src/cross_directory.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index e94a22108ea4..a03f3968b42c 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -95,6 +95,7 @@ class XDirectory extends XFileEntity { /// Lists the sub-directories and files of this directory. Stream list() { + // Converts PlatformXFileEntities to XFileEntities. return platform.list(ListParams()).map(( PlatformXFileEntity entity, ) { From 784192dddef7d52e1b0a56f057162873a9138d54 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:21:54 -0400 Subject: [PATCH 234/398] use internal to hide platform use --- packages/cross_file/cross_file/lib/src/cross_directory.dart | 4 +++- packages/cross_file/cross_file/lib/src/cross_file.dart | 5 ++++- .../cross_file/cross_file/lib/src/cross_file_entity.dart | 4 +++- .../cross_file/lib/src/scoped_storage_cross_directory.dart | 4 +++- .../cross_file/lib/src/scoped_storage_cross_file.dart | 4 +++- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index a03f3968b42c..e2fe4daf0d14 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable, internal; import 'cross_file.dart'; import 'cross_file_entity.dart'; @@ -72,9 +72,11 @@ class XDirectory extends XFileEntity { : this.fromPlatform(PlatformXDirectory(params)); /// Constructs a [XDirectory] from a specific platform implementation. + @internal const XDirectory.fromPlatform(PlatformXDirectory super.platform); /// Implementation of [PlatformXDirectory] for the current platform. + @internal @override PlatformXDirectory get platform => super.platform as PlatformXDirectory; diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index d9772782e39a..051edc5e45df 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -3,9 +3,10 @@ // found in the LICENSE file. import 'dart:convert'; +import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable, internal; import 'cross_file_entity.dart'; @@ -66,9 +67,11 @@ class XFile extends XFileEntity { : this.fromPlatform(PlatformXFile(params)); /// Constructs a [XFile] from a specific platform implementation. + @internal const XFile.fromPlatform(PlatformXFile super.platform); /// Implementation of [XFile] for the current platform. + @internal @override PlatformXFile get platform => super.platform as PlatformXFile; diff --git a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart index c6eb1152f8d5..afea98b24d3d 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file_entity.dart @@ -3,16 +3,18 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable, internal, protected; /// The common superclass for [XFile] and [XDirectory]. @immutable class XFileEntity { /// Constructs a [XFileEntity]. @protected + @internal const XFileEntity(this.platform); /// Implementation of [XFileEntity] for the current platform. + @internal final PlatformXFileEntity platform; /// A string used to reference the resource's location. diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index b337cdccb532..5b61c5428f1e 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart' show immutable; +import 'package:flutter/foundation.dart' show immutable, internal; import 'cross_directory.dart'; @@ -74,10 +74,12 @@ class ScopedStorageXDirectory extends XDirectory { /// Constructs a [ScopedStorageXDirectory] from a specific platform /// implementation. + @internal const ScopedStorageXDirectory.fromPlatform( PlatformScopedStorageXDirectory super.platform, ) : super.fromPlatform(); + @internal @override PlatformScopedStorageXDirectory get platform => super.platform as PlatformScopedStorageXDirectory; diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index f84ef6610478..406b9b694ff9 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart' show immutable; +import 'package:flutter/foundation.dart' show immutable, internal; import 'cross_file.dart'; @@ -72,10 +72,12 @@ class ScopedStorageXFile extends XFile { ) : this.fromPlatform(PlatformScopedStorageXFile(params)); /// Constructs a [ScopedStorageXFile] from a specific platform implementation. + @internal const ScopedStorageXFile.fromPlatform( PlatformScopedStorageXFile super.platform, ) : super.fromPlatform(); + @internal @override PlatformScopedStorageXFile get platform => super.platform as PlatformScopedStorageXFile; From 8ac420cabd1e67d4d82c7642b9d23580f51535ba Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:23:38 -0400 Subject: [PATCH 235/398] typo an extra can read test --- .../lib/src/scoped_storage_cross_file.dart | 2 +- .../test/scoped_storage_cross_file_test.dart | 13 ------------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 406b9b694ff9..39f803867485 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -7,7 +7,7 @@ import 'package:flutter/foundation.dart' show immutable, internal; import 'cross_file.dart'; -/// A reference to a local data resource within a devices scoped storage. +/// A reference to a local data resource within a device's scoped storage. /// /// Scoped storage limits app access to external storage and apps may lose /// access to a resource at some point depending on the platform. diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart index 2d65d4081807..f33b3597ecd5 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart @@ -93,19 +93,6 @@ void main() { expect(await file.readAsString(), message); }); - test('canRead', () async { - const canRead = false; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile(params, onCanRead: () async => canRead), - ); - - final file = ScopedStorageXFile(uri: 'uri'); - - expect(await file.canRead(), canRead); - }); - test('exists', () async { const exists = true; CrossFilePlatform.instance = TestCrossFilePlatform( From 170f6b0a304d10cc19f7d205cf6018db4999e7b1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:21:11 -0400 Subject: [PATCH 236/398] todo and version setting --- packages/cross_file/cross_file_android/CHANGELOG.md | 2 +- .../cross_file_android/example/pubspec.yaml | 13 ++++++++----- packages/cross_file/cross_file_android/pubspec.yaml | 2 +- packages/cross_file/cross_file_darwin/CHANGELOG.md | 2 +- .../cross_file_darwin/example/pubspec.yaml | 3 +++ packages/cross_file/cross_file_darwin/pubspec.yaml | 2 +- packages/cross_file/cross_file_io/CHANGELOG.md | 2 +- .../cross_file/cross_file_io/example/pubspec.yaml | 3 +++ packages/cross_file/cross_file_io/pubspec.yaml | 2 +- packages/cross_file/cross_file_web/CHANGELOG.md | 2 +- .../cross_file/cross_file_web/example/pubspec.yaml | 3 +++ packages/cross_file/cross_file_web/pubspec.yaml | 2 +- 12 files changed, 25 insertions(+), 13 deletions(-) diff --git a/packages/cross_file/cross_file_android/CHANGELOG.md b/packages/cross_file/cross_file_android/CHANGELOG.md index d0bd041d0ff6..6073234226b2 100644 --- a/packages/cross_file/cross_file_android/CHANGELOG.md +++ b/packages/cross_file/cross_file_android/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 0.1.0 * Initial release. diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index 748f4c2630b6..f6f3935299ce 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -27,10 +27,13 @@ flutter: uses-material-design: true dependency_overrides: - # When depending on this package from a real application you should use: - # cross_file_android: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. + # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because + # the updated file_selector branch depends on cross_file_android from git and this overrides its + # dependency. cross_file_android: + # When depending on this package from a real application you should use: + # cross_file_android: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. path: ../ diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 5a44fa747dce..4c06d9e2f1d1 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_android description: Implementation of cross_file_platform_interface for Android. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.0.1 +version: 0.1.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_darwin/CHANGELOG.md b/packages/cross_file/cross_file_darwin/CHANGELOG.md index d0bd041d0ff6..6073234226b2 100644 --- a/packages/cross_file/cross_file_darwin/CHANGELOG.md +++ b/packages/cross_file/cross_file_darwin/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 0.1.0 * Initial release. diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index dd493f160dc7..7998440d3be6 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -29,6 +29,9 @@ flutter: - assets/hello.txt dependency_overrides: + # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because + # the updated file_selector branch depends on cross_file_darwin from git and this overrides its + # dependency. cross_file_darwin: # When depending on this package from a real application you should use: # cross_file_darwin: ^x.y.z diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 711df43aaa74..7fbaac357410 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_darwin description: Implementation of cross_file_platform_interface for iOS and macOS. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_darwin issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.0.1 +version: 0.1.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_io/CHANGELOG.md b/packages/cross_file/cross_file_io/CHANGELOG.md index d0bd041d0ff6..6073234226b2 100644 --- a/packages/cross_file/cross_file_io/CHANGELOG.md +++ b/packages/cross_file/cross_file_io/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 0.1.0 * Initial release. diff --git a/packages/cross_file/cross_file_io/example/pubspec.yaml b/packages/cross_file/cross_file_io/example/pubspec.yaml index 6ec7185edcd1..f956a0466c67 100644 --- a/packages/cross_file/cross_file_io/example/pubspec.yaml +++ b/packages/cross_file/cross_file_io/example/pubspec.yaml @@ -38,6 +38,9 @@ flutter: - assets/hello.txt dependency_overrides: + # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because + # the updated file_selector branch depends on cross_file_io from git and this overrides its + # dependency. cross_file_io: # When depending on this package from a real application you should use: # cross_file_io: ^x.y.z diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index 9bec5e2de10a..b2e3dbc33011 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_io description: Implementation of cross_file_platform_interface for dart:io. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_io issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.0.1 +version: 0.1.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_web/CHANGELOG.md b/packages/cross_file/cross_file_web/CHANGELOG.md index d0bd041d0ff6..6073234226b2 100644 --- a/packages/cross_file/cross_file_web/CHANGELOG.md +++ b/packages/cross_file/cross_file_web/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 0.1.0 * Initial release. diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index 61148b45c75b..f0dba25d5205 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -22,6 +22,9 @@ dev_dependencies: sdk: flutter dependency_overrides: + # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because + # the updated file_selector branch depends on cross_file_web from git and this overrides its + # dependency. cross_file_web: # When depending on this package from a real application you should use: # cross_file_web: ^x.y.z diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 7da5af76eaf6..a7b80149c293 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_web description: Implementation of cross_file_platform_interface for web. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.0.1 +version: 0.1.0 publish_to: none environment: From 7fee973a32a77e781cd5aefa2ec1b91356f5c135 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:21:32 -0400 Subject: [PATCH 237/398] change version of platform interface --- packages/cross_file/cross_file_platform_interface/CHANGELOG.md | 2 +- packages/cross_file/cross_file_platform_interface/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/CHANGELOG.md b/packages/cross_file/cross_file_platform_interface/CHANGELOG.md index d0bd041d0ff6..6073234226b2 100644 --- a/packages/cross_file/cross_file_platform_interface/CHANGELOG.md +++ b/packages/cross_file/cross_file_platform_interface/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 0.1.0 * Initial release. diff --git a/packages/cross_file/cross_file_platform_interface/pubspec.yaml b/packages/cross_file/cross_file_platform_interface/pubspec.yaml index c8bfd529528d..545a8924b67f 100644 --- a/packages/cross_file/cross_file_platform_interface/pubspec.yaml +++ b/packages/cross_file/cross_file_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cr issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 # 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: 0.0.1 +version: 0.1.0 publish_to: none environment: From 7390bfc44aba4e1a987c5872cc644e1fea2e914a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:27:25 -0400 Subject: [PATCH 238/398] Pr feedback --- .../cross_file_darwin/CrossFileDarwinPlugin.swift | 10 ---------- .../example/ios/Flutter/Debug.xcconfig | 2 -- .../example/ios/Flutter/Release.xcconfig | 2 -- .../Assets.xcassets/LaunchImage.imageset/README.md | 5 ----- .../example/macos/Flutter/Flutter-Debug.xcconfig | 2 -- .../example/macos/Flutter/Flutter-Release.xcconfig | 2 -- 6 files changed, 23 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md delete mode 100644 packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig delete mode 100644 packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift index cf1fdcb6f1ef..7a32422006bb 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift @@ -20,14 +20,4 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: CrossFileDarwinApiImpl()) } - - public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - #if os(iOS) - let messenger = registrar.messenger() - #elseif os(macOS) - let messenger = registrar.messenger - #endif - - CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: nil) - } } diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig deleted file mode 100644 index ec97fc6f3021..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig deleted file mode 100644 index c4855bfe2000..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725b70f1..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig deleted file mode 100644 index 4b81f9b2d200..000000000000 --- a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig deleted file mode 100644 index 5caa9d1579e4..000000000000 --- a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" -#include "ephemeral/Flutter-Generated.xcconfig" From 3cf62e967cc815e1789d14d7c8df11dc61680217 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:30:31 -0400 Subject: [PATCH 239/398] authors --- packages/cross_file/cross_file_android/AUTHORS | 6 ++++++ packages/cross_file/cross_file_darwin/AUTHORS | 6 ++++++ packages/cross_file/cross_file_io/AUTHORS | 2 +- packages/cross_file/cross_file_platform_interface/AUTHORS | 2 +- packages/cross_file/cross_file_web/AUTHORS | 6 ++++++ 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 packages/cross_file/cross_file_android/AUTHORS create mode 100644 packages/cross_file/cross_file_darwin/AUTHORS create mode 100644 packages/cross_file/cross_file_web/AUTHORS diff --git a/packages/cross_file/cross_file_android/AUTHORS b/packages/cross_file/cross_file_android/AUTHORS new file mode 100644 index 000000000000..a4a27429da16 --- /dev/null +++ b/packages/cross_file/cross_file_android/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google LLC diff --git a/packages/cross_file/cross_file_darwin/AUTHORS b/packages/cross_file/cross_file_darwin/AUTHORS new file mode 100644 index 000000000000..a4a27429da16 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google LLC diff --git a/packages/cross_file/cross_file_io/AUTHORS b/packages/cross_file/cross_file_io/AUTHORS index 557dff97933b..a4a27429da16 100644 --- a/packages/cross_file/cross_file_io/AUTHORS +++ b/packages/cross_file/cross_file_io/AUTHORS @@ -3,4 +3,4 @@ # # Name/Organization -Google Inc. +Google LLC diff --git a/packages/cross_file/cross_file_platform_interface/AUTHORS b/packages/cross_file/cross_file_platform_interface/AUTHORS index 557dff97933b..a4a27429da16 100644 --- a/packages/cross_file/cross_file_platform_interface/AUTHORS +++ b/packages/cross_file/cross_file_platform_interface/AUTHORS @@ -3,4 +3,4 @@ # # Name/Organization -Google Inc. +Google LLC diff --git a/packages/cross_file/cross_file_web/AUTHORS b/packages/cross_file/cross_file_web/AUTHORS new file mode 100644 index 000000000000..a4a27429da16 --- /dev/null +++ b/packages/cross_file/cross_file_web/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the Flutter project. Names should be added to the list like so: +# +# Name/Organization + +Google LLC From 3f2f880050e876249f2a91227ff07c73cac8025f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:17:49 -0400 Subject: [PATCH 240/398] call stop automatically with finalizer --- .../lib/src/darwin_scoped_storage_cross_file.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 59aefa82096a..a438a17ea682 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -42,7 +42,16 @@ base class DarwinScopedStorageXFileCreationParams base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile with DarwinScopedStorageXFileExtension { /// Constructs a [DarwinScopedStorageXFile]. - DarwinScopedStorageXFile(super.params) : super.implementation(); + DarwinScopedStorageXFile(super.params) : super.implementation() { + _finalizer.attach(this, params.uri); + } + + static final Finalizer _finalizer = Finalizer((String url) { + // Check that this is not called during a unit test. + if (Platform.environment['FLUTTER_TEST'] != 'true') { + CrossFileDarwinApi().stopAccessingSecurityScopedResource(url); + } + }); late final _file = File.fromUri(Uri.parse(params.uri)); From f9ba45a70840c2a71bd6acfbc7cd24456d94cfac Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:58:24 -0400 Subject: [PATCH 241/398] change all to platformxentity and xentity --- .../cross_file/example/lib/main.dart | 2 +- .../cross_file/cross_file/lib/cross_file.dart | 2 +- .../cross_file/lib/src/cross_directory.dart | 14 ++++++------- ...oss_file_entity.dart => cross_entity.dart} | 10 +++++----- .../cross_file/lib/src/cross_file.dart | 4 ++-- .../cross_file/test/cross_directory_test.dart | 8 ++++---- .../scoped_storage_cross_directory_test.dart | 8 ++++---- .../cross_file/test/test_stubs.dart | 12 +++++------ .../cross_file_android/example/lib/main.dart | 2 +- .../lib/cross_file_android.dart | 2 +- ...ndroid_scoped_storage_cross_directory.dart | 2 +- .../android_scoped_storage_cross_file.dart | 3 ++- ...d_scoped_storage_cross_directory_test.dart | 2 +- .../cross_file_darwin/example/lib/main.dart | 2 +- .../lib/cross_file_darwin.dart | 2 +- ...darwin_scoped_storage_cross_directory.dart | 2 +- ...n_scoped_storage_cross_directory_test.dart | 2 +- .../cross_file_io/example/lib/main.dart | 2 +- .../cross_file_io/lib/cross_file_io.dart | 4 ++-- .../lib/src/io_cross_directory.dart | 4 ++-- .../cross_file_io/lib/src/io_cross_file.dart | 3 ++- .../test/io_cross_directory_test.dart | 2 +- .../lib/cross_file_platform_interface.dart | 2 +- .../lib/src/cross_file_platform.dart | 7 +++---- .../lib/src/platform_cross_directory.dart | 12 +++++------ ...entity.dart => platform_cross_entity.dart} | 20 +++++++++---------- .../lib/src/platform_cross_file.dart | 11 +++++----- .../cross_file_web/example/lib/main.dart | 2 +- .../cross_file_web/lib/cross_file_web.dart | 2 +- .../src/web_scoped_storage_cross_file.dart | 3 ++- 30 files changed, 78 insertions(+), 75 deletions(-) rename packages/cross_file/cross_file/lib/src/{cross_file_entity.dart => cross_entity.dart} (76%) rename packages/cross_file/cross_file_platform_interface/lib/src/{platform_cross_file_entity.dart => platform_cross_entity.dart} (58%) diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index 0a9282069d3c..8098b98b804d 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -54,7 +54,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XFileEntity entity in directory.list()) { + await for (final XEntity entity in directory.list()) { switch (entity) { case final XFile file: final String filename = await file.name() ?? file.uri; diff --git a/packages/cross_file/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart index afda4f9eb36b..73898c73bec6 100644 --- a/packages/cross_file/cross_file/lib/cross_file.dart +++ b/packages/cross_file/cross_file/lib/cross_file.dart @@ -4,6 +4,6 @@ export 'src/cross_directory.dart'; export 'src/cross_file.dart'; -export 'src/cross_file_entity.dart'; +export 'src/cross_entity.dart'; export 'src/scoped_storage_cross_directory.dart'; export 'src/scoped_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index e2fe4daf0d14..d38f9c30aa36 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -5,8 +5,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart' show immutable, internal; +import 'cross_entity.dart'; import 'cross_file.dart'; -import 'cross_file_entity.dart'; import 'scoped_storage_cross_directory.dart'; import 'scoped_storage_cross_file.dart'; @@ -33,7 +33,7 @@ import 'scoped_storage_cross_file.dart'; /// } /// ``` @immutable -class XDirectory extends XFileEntity { +class XDirectory extends XEntity { /// Constructs a [XDirectory]. /// /// See [XDirectory.fromCreationParams] for setting parameters for a specific @@ -96,10 +96,10 @@ class XDirectory extends XFileEntity { } /// Lists the sub-directories and files of this directory. - Stream list() { - // Converts PlatformXFileEntities to XFileEntities. - return platform.list(ListParams()).map(( - PlatformXFileEntity entity, + Stream list() { + // Converts PlatformXEntities to XEntities. + return platform.list(ListParams()).map(( + PlatformXEntity entity, ) { switch (entity) { case PlatformXFile(): @@ -114,7 +114,7 @@ class XDirectory extends XFileEntity { return XDirectory.fromPlatform(entity); } - return XFileEntity(entity); + return XEntity(entity); }); } } diff --git a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart b/packages/cross_file/cross_file/lib/src/cross_entity.dart similarity index 76% rename from packages/cross_file/cross_file/lib/src/cross_file_entity.dart rename to packages/cross_file/cross_file/lib/src/cross_entity.dart index afea98b24d3d..ef6cd40c4e5b 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_entity.dart @@ -7,15 +7,15 @@ import 'package:flutter/foundation.dart' show immutable, internal, protected; /// The common superclass for [XFile] and [XDirectory]. @immutable -class XFileEntity { - /// Constructs a [XFileEntity]. +class XEntity { + /// Constructs a [XEntity]. @protected @internal - const XFileEntity(this.platform); + const XEntity(this.platform); - /// Implementation of [XFileEntity] for the current platform. + /// Implementation of [XEntity] for the current platform. @internal - final PlatformXFileEntity platform; + final PlatformXEntity platform; /// A string used to reference the resource's location. String get uri => platform.params.uri; diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 051edc5e45df..13974735a3c0 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -8,7 +8,7 @@ import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart' show immutable, internal; -import 'cross_file_entity.dart'; +import 'cross_entity.dart'; /// A reference to a local data resource. /// @@ -31,7 +31,7 @@ import 'cross_file_entity.dart'; /// } /// ``` @immutable -class XFile extends XFileEntity { +class XFile extends XEntity { /// Constructs a [XFile]. /// /// See [XFile.fromCreationParams] for setting parameters for a specific diff --git a/packages/cross_file/cross_file/test/cross_directory_test.dart b/packages/cross_file/cross_file/test/cross_directory_test.dart index a368ce1cd288..4ba77f3d5009 100644 --- a/packages/cross_file/cross_file/test/cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/cross_directory_test.dart @@ -23,10 +23,10 @@ void main() { }); test('list', () async { - final entities = [ + final entities = [ TestXFile(const PlatformXFileCreationParams(uri: 'uri1')), TestXDirectory(const PlatformXDirectoryCreationParams(uri: 'uri2')), - TestXFileEntity(const PlatformXFileCreationParams(uri: 'uri3')), + TestXEntity(const PlatformXFileCreationParams(uri: 'uri3')), ]; CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformXDirectory: (PlatformXDirectoryCreationParams params) => @@ -38,7 +38,7 @@ void main() { final directory = XDirectory(uri: 'uri'); - final List directoryEntities = await directory + final List directoryEntities = await directory .list() .toList(); expect(directoryEntities.length, entities.length); @@ -46,7 +46,7 @@ void main() { expect(directoryEntities.first.uri, entities.first.params.uri); expect(directoryEntities[1], isA()); expect(directoryEntities[1].uri, entities[1].params.uri); - expect(directoryEntities[2], isA()); + expect(directoryEntities[2], isA()); expect(directoryEntities[2].uri, entities[2].params.uri); }); }); diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 9d8b4ddc4f44..21ca5b231b77 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -27,14 +27,14 @@ void main() { }); test('list', () async { - final entities = [ + final entities = [ TestScopedStorageXFile( const PlatformScopedStorageXFileCreationParams(uri: 'uri1'), ), TestScopedStorageXDirectory( const PlatformScopedStorageXDirectoryCreationParams(uri: 'uri2'), ), - TestXFileEntity(const PlatformXFileCreationParams(uri: 'uri3')), + TestXEntity(const PlatformXFileCreationParams(uri: 'uri3')), ]; CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformScopedStorageXDirectory: @@ -47,7 +47,7 @@ void main() { final directory = ScopedStorageXDirectory(uri: 'uri'); - final List directoryEntities = await directory + final List directoryEntities = await directory .list() .toList(); expect(directoryEntities.length, entities.length); @@ -55,7 +55,7 @@ void main() { expect(directoryEntities.first.uri, entities.first.params.uri); expect(directoryEntities[1], isA()); expect(directoryEntities[1].uri, entities[1].params.uri); - expect(directoryEntities[2], isA()); + expect(directoryEntities[2], isA()); expect(directoryEntities[2].uri, entities[2].params.uri); }); }); diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 5a397b2395ce..480b31a20e15 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -124,7 +124,7 @@ final class TestXDirectory extends PlatformXDirectory { : super.implementation(); Future Function()? onExists; - Stream Function(ListParams params)? onList; + Stream Function(ListParams params)? onList; @override Future exists() async { @@ -132,7 +132,7 @@ final class TestXDirectory extends PlatformXDirectory { } @override - Stream list(ListParams params) async* { + Stream list(ListParams params) async* { if (onList != null) { yield* onList!.call(params); } @@ -210,7 +210,7 @@ final class TestScopedStorageXDirectory : super.implementation(); Future Function()? onExists; - Stream Function(ListParams params)? onList; + Stream Function(ListParams params)? onList; @override Future exists() async { @@ -218,15 +218,15 @@ final class TestScopedStorageXDirectory } @override - Stream list(ListParams params) async* { + Stream list(ListParams params) async* { if (onList != null) { yield* onList!.call(params); } } } -final class TestXFileEntity extends PlatformXFileEntity { - TestXFileEntity(super.params, {this.onExists}); +final class TestXEntity extends PlatformXEntity { + TestXEntity(super.params, {this.onExists}); Future Function()? onExists; diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 0a9282069d3c..8098b98b804d 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -54,7 +54,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XFileEntity entity in directory.list()) { + await for (final XEntity entity in directory.list()) { switch (entity) { case final XFile file: final String filename = await file.name() ?? file.uri; diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index dc71ec375c41..c8b851140d17 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -7,6 +7,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart ListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, - PlatformXFileEntity; + PlatformXEntity; export 'src/cross_file_android.dart'; diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index ef0d2363e578..4789b69f44d9 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -23,7 +23,7 @@ base class AndroidScopedStorageXDirectory } @override - Stream list(ListParams params) async* { + Stream list(ListParams params) async* { for (final DocumentFile documentFile in await _documentFile.listFiles()) { final String uri = await documentFile.getUri(); if (await documentFile.isFile()) { diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 6f32c7e24bcd..c127b71108a1 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -4,9 +4,10 @@ import 'dart:convert'; import 'dart:math'; +import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show visibleForTesting; import 'android_library.g.dart' as android; diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart index 9d8059f5de82..cbedeef59d2a 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart @@ -67,7 +67,7 @@ void main() { final List entityUris = await dir .list(ListParams()) - .map((PlatformXFileEntity entity) => entity.params.uri) + .map((PlatformXEntity entity) => entity.params.uri) .toList(); expect(entityUris, [fileUri]); diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 0fefe2af66c1..4c4f58a8a56c 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -54,7 +54,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XFileEntity entity in directory.list()) { + await for (final XEntity entity in directory.list()) { switch (entity) { case final XFile file: final String filename = await file.name() ?? file.uri; diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index b9979adee001..aa69e55089dd 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -7,7 +7,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart ListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, - PlatformXFileEntity; + PlatformXEntity; export 'src/cross_file_darwin.dart'; export 'src/darwin_scoped_storage_cross_directory.dart' diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 3690eebda288..f1e9821e2448 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -63,7 +63,7 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory Future exists() async => _directory.existsSync(); @override - Stream list(ListParams params) async* { + Stream list(ListParams params) async* { await for (final FileSystemEntity entity in _directory.list()) { switch (entity) { case final Directory directory: diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart index aa32d59f42d0..48042f209cdc 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -46,7 +46,7 @@ void main() { expect( (await directory.list(ListParams()).toList()).map( - (PlatformXFileEntity entity) => entity.params.uri, + (PlatformXEntity entity) => entity.params.uri, ), (await testDirectory.list().toList()).map( (FileSystemEntity entity) => entity.uri.toString(), diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart index da54acf95606..9455cfbad20e 100644 --- a/packages/cross_file/cross_file_io/example/lib/main.dart +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -51,7 +51,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XFileEntity entity in directory.list()) { + await for (final XEntity entity in directory.list()) { switch (entity) { case final XFile file: final String filename = await file.name() ?? file.uri; diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 9fd4cfeb7f6b..ce084ca77716 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -6,8 +6,8 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXDirectoryCreationParams, - PlatformXFileCreationParams, - PlatformXFileEntity; + PlatformXEntity, + PlatformXFileCreationParams; export 'src/cross_file_io.dart'; export 'src/io_cross_directory.dart'; diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart index 380ce720751c..499522048edb 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -5,7 +5,7 @@ import 'dart:io'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable; import 'io_cross_file.dart'; @@ -52,7 +52,7 @@ base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { Future exists() async => directory.existsSync(); @override - Stream list(ListParams params) async* { + Stream list(ListParams params) async* { await for (final FileSystemEntity entity in directory.list()) { switch (entity) { case final Directory directory: diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 5e3b80de26bc..e482bd31df74 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -4,9 +4,10 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable; import 'package:path/path.dart' as path; /// Implementation of [PlatformXFileCreationParams] for dart:io. diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart index 62b7ee4a815d..cee64ff41677 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -34,7 +34,7 @@ void main() { expect( (await directory.list(ListParams()).toList()).map( - (PlatformXFileEntity entity) => entity.params.uri, + (PlatformXEntity entity) => entity.params.uri, ), (await testDirectory.list().toList()).map( (FileSystemEntity entity) => entity.uri.toString(), diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index a6a1a738d73a..777fe8044c2d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -4,7 +4,7 @@ export 'src/cross_file_platform.dart'; export 'src/platform_cross_directory.dart'; +export 'src/platform_cross_entity.dart'; export 'src/platform_cross_file.dart'; -export 'src/platform_cross_file_entity.dart'; export 'src/scoped_storage/platform_scoped_storage_cross_directory.dart'; export 'src/scoped_storage/platform_scoped_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 9ae461bd324a..48191f40b019 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -3,12 +3,11 @@ // found in the LICENSE file. import 'dart:convert'; - import 'dart:typed_data'; import 'platform_cross_directory.dart'; +import 'platform_cross_entity.dart'; import 'platform_cross_file.dart'; -import 'platform_cross_file_entity.dart'; import 'scoped_storage/platform_scoped_storage_cross_directory.dart'; import 'scoped_storage/platform_scoped_storage_cross_file.dart'; @@ -89,7 +88,7 @@ final class _DefaultXDirectory extends PlatformXDirectory { Future exists() async => false; @override - Stream list(ListParams params) { + Stream list(ListParams params) { throw UnsupportedError('This instance does not represent any directory.'); } } @@ -140,7 +139,7 @@ final class _DefaultScopedStorageXDirectory Future exists() async => false; @override - Stream list(ListParams params) { + Stream list(ListParams params) { throw UnsupportedError('This instance does not represent any directory.'); } } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index cc945fbd7062..afdb85a56633 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -4,10 +4,10 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable, protected; import 'cross_file_platform.dart'; -import 'platform_cross_file_entity.dart'; +import 'platform_cross_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXDirectory]. /// @@ -41,7 +41,7 @@ import 'platform_cross_file_entity.dart'; /// ``` @immutable base class PlatformXDirectoryCreationParams - extends PlatformXFileEntityCreationParams { + extends PlatformXEntityCreationParams { /// Constructs a [PlatformXDirectoryCreationParams]. const PlatformXDirectoryCreationParams({required super.uri}); } @@ -67,10 +67,10 @@ base class PlatformXDirectoryCreationParams /// Future platformMethod(); /// } /// ``` -mixin PlatformXDirectoryExtension implements PlatformXFileEntityExtension {} +mixin PlatformXDirectoryExtension implements PlatformXEntityExtension {} /// Interface for a reference to a directory (or folder) on the file system. -abstract base class PlatformXDirectory extends PlatformXFileEntity { +abstract base class PlatformXDirectory extends PlatformXEntity { /// Creates a new [PlatformXDirectory]. factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { assert( @@ -100,7 +100,7 @@ abstract base class PlatformXDirectory extends PlatformXFileEntity { /// /// Platforms may throw an exception if there is an error listing entities in /// the directory - Stream list(ListParams params); + Stream list(ListParams params); } /// Base class for parameters passed to [PlatformXDirectory.list]. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart similarity index 58% rename from packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart rename to packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart index 2c15f5849939..1be3386741f5 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart @@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable; /// The common superclass for [PlatformXFileCreationParams] and /// [PlatformXDirectoryCreationParams]. @immutable -abstract base class PlatformXFileEntityCreationParams { - /// Constructs a [PlatformXFileCreationParams]. - const PlatformXFileEntityCreationParams({required this.uri}); +abstract base class PlatformXEntityCreationParams { + /// Constructs a [PlatformXEntityCreationParams]. + const PlatformXEntityCreationParams({required this.uri}); /// A string used to reference the resource's location. final String uri; @@ -17,18 +17,18 @@ abstract base class PlatformXFileEntityCreationParams { /// The common superclass for [PlatformXFileExtension] and /// [PlatformXDirectoryExtension]. -mixin PlatformXFileEntityExtension {} +mixin PlatformXEntityExtension {} /// The common superclass for [PlatformXFile] and [PlatformXDirectory]. -abstract base class PlatformXFileEntity { +abstract base class PlatformXEntity { /// Constructs a [PlatformCrossFileEntity]. - PlatformXFileEntity(this.params); + PlatformXEntity(this.params); - /// The parameters used to initialize the [PlatformXFileEntity]. - final PlatformXFileEntityCreationParams params; + /// The parameters used to initialize the [PlatformXEntity]. + final PlatformXEntityCreationParams params; /// Extension for providing platform specific features. - PlatformXFileEntityExtension? get extension => null; + PlatformXEntityExtension? get extension => null; /// Whether the resource represented by this reference exists. Future exists(); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index cfbcab742471..324f2c7e423b 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -3,11 +3,12 @@ // found in the LICENSE file. import 'dart:convert'; +import 'dart:typed_data'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable, protected; import 'cross_file_platform.dart'; -import 'platform_cross_file_entity.dart'; +import 'platform_cross_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXFile]. /// @@ -41,7 +42,7 @@ import 'platform_cross_file_entity.dart'; /// ``` @immutable base class PlatformXFileCreationParams - extends PlatformXFileEntityCreationParams { + extends PlatformXEntityCreationParams { /// Constructs a [PlatformXFileCreationParams]. const PlatformXFileCreationParams({required super.uri}); } @@ -67,10 +68,10 @@ base class PlatformXFileCreationParams /// Future platformMethod(); /// } /// ``` -mixin PlatformXFileExtension implements PlatformXFileEntityExtension {} +mixin PlatformXFileExtension implements PlatformXEntityExtension {} /// Interface for a reference to a local data resource. -abstract base class PlatformXFile extends PlatformXFileEntity { +abstract base class PlatformXFile extends PlatformXEntity { /// Creates a new [PlatformXFile]. factory PlatformXFile(PlatformXFileCreationParams params) { assert( diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index afcf367f6096..1140ca51d051 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -54,7 +54,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XFileEntity entity in directory.list()) { + await for (final XEntity entity in directory.list()) { switch (entity) { case final XFile file: final String filename = await file.name() ?? file.uri; diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 2aaceef7f335..dd9941a3a984 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -7,7 +7,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart ListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, - PlatformXFileEntity; + PlatformXEntity; export 'src/cross_file_web.dart'; export 'src/web_scoped_storage_cross_file.dart' diff --git a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart index 64a093852025..36443d6edb64 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart @@ -4,9 +4,10 @@ import 'dart:convert'; import 'dart:js_interop'; +import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart'; +import 'package:flutter/foundation.dart' show immutable, visibleForTesting; import 'package:web/web.dart'; import 'web_helpers.dart'; From 4a49a219eb22a9942e8a3fbb895d54ce49593a7f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:04:48 -0400 Subject: [PATCH 242/398] formatting --- packages/cross_file/cross_file/lib/src/cross_directory.dart | 4 +--- packages/cross_file/cross_file/test/cross_directory_test.dart | 4 +--- .../cross_file/test/scoped_storage_cross_directory_test.dart | 4 +--- .../lib/src/platform_cross_file.dart | 3 +-- 4 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index d38f9c30aa36..604636e93bea 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -98,9 +98,7 @@ class XDirectory extends XEntity { /// Lists the sub-directories and files of this directory. Stream list() { // Converts PlatformXEntities to XEntities. - return platform.list(ListParams()).map(( - PlatformXEntity entity, - ) { + return platform.list(ListParams()).map((PlatformXEntity entity) { switch (entity) { case PlatformXFile(): if (entity case PlatformScopedStorageXFile()) { diff --git a/packages/cross_file/cross_file/test/cross_directory_test.dart b/packages/cross_file/cross_file/test/cross_directory_test.dart index 4ba77f3d5009..9cadc0b16049 100644 --- a/packages/cross_file/cross_file/test/cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/cross_directory_test.dart @@ -38,9 +38,7 @@ void main() { final directory = XDirectory(uri: 'uri'); - final List directoryEntities = await directory - .list() - .toList(); + final List directoryEntities = await directory.list().toList(); expect(directoryEntities.length, entities.length); expect(directoryEntities.first, isA()); expect(directoryEntities.first.uri, entities.first.params.uri); diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 21ca5b231b77..327c1d748b6d 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -47,9 +47,7 @@ void main() { final directory = ScopedStorageXDirectory(uri: 'uri'); - final List directoryEntities = await directory - .list() - .toList(); + final List directoryEntities = await directory.list().toList(); expect(directoryEntities.length, entities.length); expect(directoryEntities.first, isA()); expect(directoryEntities.first.uri, entities.first.params.uri); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 324f2c7e423b..8fe7be660a5d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -41,8 +41,7 @@ import 'platform_cross_entity.dart'; /// } /// ``` @immutable -base class PlatformXFileCreationParams - extends PlatformXEntityCreationParams { +base class PlatformXFileCreationParams extends PlatformXEntityCreationParams { /// Constructs a [PlatformXFileCreationParams]. const PlatformXFileCreationParams({required super.uri}); } From 30210f13ceab03e2374b6aee283da162977b5190 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:49:38 -0400 Subject: [PATCH 243/398] sort exports --- packages/cross_file/cross_file/lib/cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart index 73898c73bec6..b728b35fa63d 100644 --- a/packages/cross_file/cross_file/lib/cross_file.dart +++ b/packages/cross_file/cross_file/lib/cross_file.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. export 'src/cross_directory.dart'; -export 'src/cross_file.dart'; export 'src/cross_entity.dart'; +export 'src/cross_file.dart'; export 'src/scoped_storage_cross_directory.dart'; export 'src/scoped_storage_cross_file.dart'; From a388a69666acc6d8d6b48613a1b199d4ce61f5ef Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 21 Apr 2026 20:34:22 -0400 Subject: [PATCH 244/398] add xcconfig back --- .../cross_file_darwin/example/ios/Flutter/Debug.xcconfig | 1 + .../cross_file_darwin/example/ios/Flutter/Release.xcconfig | 1 + 2 files changed, 2 insertions(+) create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 000000000000..592ceee85b89 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig new file mode 100644 index 000000000000..592ceee85b89 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" From a6af73c4e9da1b64027f8f85942cc3502d2a6a1b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 14:25:01 -0400 Subject: [PATCH 245/398] add missing xcconfigs --- .../example/macos/Flutter/Flutter-Debug.xcconfig | 1 + .../example/macos/Flutter/Flutter-Release.xcconfig | 1 + 2 files changed, 2 insertions(+) create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig create mode 100644 packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 000000000000..c2efd0b608ba --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 000000000000..c2efd0b608ba --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" From c93bb9376436103c061ddc27de772ef50b0225f7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:17:02 -0400 Subject: [PATCH 246/398] add finalizer to ios directory --- .../src/darwin_scoped_storage_cross_directory.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index f1e9821e2448..93eb1dd158fc 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -44,7 +44,16 @@ base class DarwinScopedStorageXDirectoryCreationParams base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory with DarwinScopedStorageXDirectoryExtension { /// Constructs a [DarwinScopedStorageXDirectory]. - DarwinScopedStorageXDirectory(super.params) : super.implementation(); + DarwinScopedStorageXDirectory(super.params) : super.implementation() { + _finalizer.attach(this, params.uri); + } + + static final Finalizer _finalizer = Finalizer((String url) { + // Check that this is not called during a unit test. + if (Platform.environment['FLUTTER_TEST'] != 'true') { + CrossFileDarwinApi().stopAccessingSecurityScopedResource(url); + } + }); late final _directory = Directory.fromUri(Uri.parse(params.uri)); From 8fecd6a17c63a6125a39f54b37727c0641c10d4c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:40:00 -0400 Subject: [PATCH 247/398] fix test --- .../cross_file/example/integration_test/cross_file_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart index 1d8e0da114ce..f11767706210 100644 --- a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -18,7 +18,7 @@ void main() { testWidgets('Can read from file using dart:io implementation', ( WidgetTester tester, ) async { - final Directory dir = await getTemporaryDirectory(); + final Directory dir = await getApplicationCacheDirectory(); final xDir = XDirectory.fromPath(dir.path); expect(await xDir.exists(), isTrue); From 531dc5c0a64435dd1e6c9753e43c27e07aab236d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 17:43:58 -0400 Subject: [PATCH 248/398] remove dupe canread test --- .../cross_file_web/test/web_cross_file_test.dart | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index fa3b4d693294..44e40595b72f 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -132,14 +132,6 @@ void main() { expect(await file.readAsString(), testFileStringContents); }); - test('canRead', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.canRead(), true); - }); - test('exists', () async { final file = PlatformScopedStorageXFile( WebScopedStorageXFileCreationParams.fromBlob(testFile), From 194a323c430928b84fa3e0f352e5df4d781a8c94 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 18:35:50 -0400 Subject: [PATCH 249/398] add dart test yaml --- packages/cross_file/cross_file_web/dart_test.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/cross_file/cross_file_web/dart_test.yaml diff --git a/packages/cross_file/cross_file_web/dart_test.yaml b/packages/cross_file/cross_file_web/dart_test.yaml new file mode 100644 index 000000000000..a883822278f5 --- /dev/null +++ b/packages/cross_file/cross_file_web/dart_test.yaml @@ -0,0 +1,6 @@ +# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments +override_platforms: + chrome: + settings: + executable: chrome + arguments: --no-sandbox \ No newline at end of file From 1a54c910c274e3ddb06e5d8bef1f4b9dda5679aa Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 19:30:45 -0400 Subject: [PATCH 250/398] add comment --- .../packages/cross_file_android/proxies/DocumentFileProxyApi.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt index 1f3ebd2bb58c..af781ce7bcc9 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt @@ -22,6 +22,7 @@ class DocumentFileProxyApi(override val pigeonRegistrar: ProxyApiRegistrar) : } override fun fromTreeUri(treeUri: String): DocumentFile { + // Only returns null on platforms below Android 19. return DocumentFile.fromTreeUri(pigeonRegistrar.context, treeUri.toUri())!! } From 5033f3f1e602d309289450043a96f6159cbab9e0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 20:01:29 -0400 Subject: [PATCH 251/398] add canread to scopedstoragecrossdirectory --- .../src/scoped_storage_cross_directory.dart | 3 +++ .../scoped_storage_cross_directory_test.dart | 16 +++++++++++++ .../cross_file/test/test_stubs.dart | 14 +++++++++-- ...ndroid_scoped_storage_cross_directory.dart | 3 +++ ...d_scoped_storage_cross_directory_test.dart | 23 +++++++++++++++++-- ...darwin_scoped_storage_cross_directory.dart | 5 ++++ ...n_scoped_storage_cross_directory_test.dart | 21 +++++++++++++---- .../lib/src/cross_file_platform.dart | 3 +++ ...atform_scoped_storage_cross_directory.dart | 3 +++ 9 files changed, 83 insertions(+), 8 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index 5b61c5428f1e..031fe4aa3c3a 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -83,4 +83,7 @@ class ScopedStorageXDirectory extends XDirectory { @override PlatformScopedStorageXDirectory get platform => super.platform as PlatformScopedStorageXDirectory; + + /// Whether the directory represented by this reference can be read. + Future canRead() => platform.canRead(); } diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 327c1d748b6d..7f8aa4df4640 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -56,5 +56,21 @@ void main() { expect(directoryEntities[2], isA()); expect(directoryEntities[2].uri, entities[2].params.uri); }); + + test('canRead', () async { + const canRead = false; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXDirectory: + (PlatformScopedStorageXDirectoryCreationParams params) => + TestScopedStorageXDirectory( + params, + onCanRead: () async => canRead, + ), + ); + + final file = ScopedStorageXDirectory(uri: 'uri'); + + expect(await file.canRead(), canRead); + }); }); } diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 480b31a20e15..401e802bc7ae 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -206,17 +206,27 @@ final class TestScopedStorageXFile extends PlatformScopedStorageXFile { final class TestScopedStorageXDirectory extends PlatformScopedStorageXDirectory { - TestScopedStorageXDirectory(super.params, {this.onExists, this.onList}) - : super.implementation(); + TestScopedStorageXDirectory( + super.params, { + this.onExists, + this.onList, + this.onCanRead, + }) : super.implementation(); Future Function()? onExists; Stream Function(ListParams params)? onList; + Future Function()? onCanRead; @override Future exists() async { return await onExists?.call() ?? false; } + @override + Future canRead() async { + return await onCanRead?.call() ?? false; + } + @override Stream list(ListParams params) async* { if (onList != null) { diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index 4789b69f44d9..691d73fce195 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -17,6 +17,9 @@ base class AndroidScopedStorageXDirectory treeUri: params.uri, ); + @override + Future canRead() => _documentFile.canRead(); + @override Future exists() async { return await _documentFile.exists() && await _documentFile.isDirectory(); diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart index cbedeef59d2a..125141be7e68 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart @@ -31,11 +31,30 @@ void main() { return mockDocumentFile; }; - final file = AndroidScopedStorageXDirectory( + final directory = AndroidScopedStorageXDirectory( const PlatformScopedStorageXDirectoryCreationParams(uri: uri), ); - expect(await file.exists(), true); + expect(await directory.exists(), true); + }); + + test('canRead', () async { + final mockDocumentFile = MockDocumentFile(); + const canRead = false; + when(mockDocumentFile.canRead()).thenAnswer((_) async => canRead); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromTreeUri = + ({required String treeUri}) { + expect(treeUri, uri); + return mockDocumentFile; + }; + + final directory = AndroidScopedStorageXDirectory( + const PlatformScopedStorageXDirectoryCreationParams(uri: uri), + ); + + expect(await directory.canRead(), canRead); }); test('list', () async { diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 93eb1dd158fc..4dfc5ec97f55 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -89,6 +89,11 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory } } + @override + Future canRead() { + return params.api.isReadableFile(params.uri); + } + @override Future startAccessingSecurityScopedResource() { return params.api.startAccessingSecurityScopedResource(params.uri); diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart index 48042f209cdc..121389ffcaab 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -54,6 +54,19 @@ void main() { ); }); + test('canRead', () async { + final mockApi = MockCrossFileDarwinApi(); + const uri = 'uri'; + const result = true; + when(mockApi.isReadableFile(uri)).thenAnswer((_) async => result); + + final directory = DarwinScopedStorageXDirectory( + DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), + ); + + expect(await directory.canRead(), result); + }); + test('startAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); final uri = testDirectory.uri.toString(); @@ -62,22 +75,22 @@ void main() { mockApi.startAccessingSecurityScopedResource(uri), ).thenAnswer((_) async => result); - final file = DarwinScopedStorageXDirectory( + final directory = DarwinScopedStorageXDirectory( DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), ); - expect(await file.startAccessingSecurityScopedResource(), result); + expect(await directory.startAccessingSecurityScopedResource(), result); }); test('stopAccessingSecurityScopedResource', () async { final mockApi = MockCrossFileDarwinApi(); final uri = testDirectory.uri.toString(); - final file = DarwinScopedStorageXDirectory( + final directory = DarwinScopedStorageXDirectory( DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), ); - await file.stopAccessingSecurityScopedResource(); + await directory.stopAccessingSecurityScopedResource(); verify(mockApi.stopAccessingSecurityScopedResource(uri)); }); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 48191f40b019..e0a0e02982e8 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -138,6 +138,9 @@ final class _DefaultScopedStorageXDirectory @override Future exists() async => false; + @override + Future canRead() async => false; + @override Stream list(ListParams params) { throw UnsupportedError('This instance does not represent any directory.'); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index 9b6fdc0d3f7c..c96a27755533 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -99,4 +99,7 @@ abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { @override PlatformScopedStorageXDirectoryCreationParams get params => super.params as PlatformScopedStorageXDirectoryCreationParams; + + /// Whether the directory represented by this reference can be read. + Future canRead(); } From fb21706ace237fc91326da1a9dbacff20dfc1ac8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 22 Apr 2026 20:02:43 -0400 Subject: [PATCH 252/398] remove config file --- packages/cross_file/cross_file_web/dart_test.yaml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 packages/cross_file/cross_file_web/dart_test.yaml diff --git a/packages/cross_file/cross_file_web/dart_test.yaml b/packages/cross_file/cross_file_web/dart_test.yaml deleted file mode 100644 index a883822278f5..000000000000 --- a/packages/cross_file/cross_file_web/dart_test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments -override_platforms: - chrome: - settings: - executable: chrome - arguments: --no-sandbox \ No newline at end of file From 939a1c0d0fb97ffe4f1bcad3ce46b24dc7238786 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 5 May 2026 11:36:50 -0400 Subject: [PATCH 253/398] make classes base --- packages/cross_file/cross_file/lib/src/cross_directory.dart | 2 +- packages/cross_file/cross_file/lib/src/cross_entity.dart | 2 +- packages/cross_file/cross_file/lib/src/cross_file.dart | 2 +- .../cross_file/lib/src/scoped_storage_cross_directory.dart | 2 +- .../cross_file/lib/src/scoped_storage_cross_file.dart | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 604636e93bea..67b81992b15d 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -33,7 +33,7 @@ import 'scoped_storage_cross_file.dart'; /// } /// ``` @immutable -class XDirectory extends XEntity { +base class XDirectory extends XEntity { /// Constructs a [XDirectory]. /// /// See [XDirectory.fromCreationParams] for setting parameters for a specific diff --git a/packages/cross_file/cross_file/lib/src/cross_entity.dart b/packages/cross_file/cross_file/lib/src/cross_entity.dart index ef6cd40c4e5b..7eb04fcd4364 100644 --- a/packages/cross_file/cross_file/lib/src/cross_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_entity.dart @@ -7,7 +7,7 @@ import 'package:flutter/foundation.dart' show immutable, internal, protected; /// The common superclass for [XFile] and [XDirectory]. @immutable -class XEntity { +base class XEntity { /// Constructs a [XEntity]. @protected @internal diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 13974735a3c0..9df74576d654 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -31,7 +31,7 @@ import 'cross_entity.dart'; /// } /// ``` @immutable -class XFile extends XEntity { +base class XFile extends XEntity { /// Constructs a [XFile]. /// /// See [XFile.fromCreationParams] for setting parameters for a specific diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index 031fe4aa3c3a..304e338c9565 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -33,7 +33,7 @@ import 'cross_directory.dart'; /// } /// ``` @immutable -class ScopedStorageXDirectory extends XDirectory { +base class ScopedStorageXDirectory extends XDirectory { /// Constructs a [ScopedStorageXDirectory]. /// /// See [ScopedStorageXDirectory.fromCreationParams] for setting parameters diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 39f803867485..5dc519b509ac 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -32,7 +32,7 @@ import 'cross_file.dart'; /// } /// ``` @immutable -class ScopedStorageXFile extends XFile { +base class ScopedStorageXFile extends XFile { /// Constructs a [ScopedStorageXFile]. /// /// See [ScopedStorageXFile.fromCreationParams] for setting parameters From c62eb168dbbcc40838e2c2504242e077d454cf0b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 5 May 2026 13:07:26 -0400 Subject: [PATCH 254/398] fix class name refs --- .../lib/src/darwin_scoped_storage_cross_directory.dart | 4 ++-- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 4dfc5ec97f55..790d1344ec4d 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -12,8 +12,8 @@ import 'cross_file_darwin_apis.g.dart'; import 'darwin_scoped_storage_cross_file.dart'; import 'security_scoped_resource.dart'; -/// Implementation of [PlatformXDirectoryCreationParams] for iOS and -/// macOS. +/// Implementation of [PlatformScopedStorageXDirectoryCreationParams] for iOS +/// and macOS. @immutable base class DarwinScopedStorageXDirectoryCreationParams extends PlatformScopedStorageXDirectoryCreationParams { diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index a438a17ea682..658f5a896bf7 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -13,7 +13,7 @@ import 'package:path/path.dart' as path; import 'cross_file_darwin_apis.g.dart'; import 'security_scoped_resource.dart'; -/// Implementation of [DarwinScopedStorageXFileCreationParams] for iOS and +/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and /// macOS. @immutable base class DarwinScopedStorageXFileCreationParams From bc284942df6379221d9434c788f8deb4e4a6490c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 6 May 2026 14:26:12 -0400 Subject: [PATCH 255/398] add photokit scaffolding in dart --- ...darwin_scoped_storage_cross_directory.dart | 4 +- .../src/darwin_scoped_storage_cross_file.dart | 155 +++++++++++++++--- 2 files changed, 134 insertions(+), 25 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 790d1344ec4d..b789d423178f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -83,7 +83,9 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory ); case final File file: yield DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: file.uri.toString()), + DarwinScopedStorageXFileCreationParams.securityScoped( + uri: file.uri.toString(), + ), ); } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 658f5a896bf7..222f66134bb4 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -13,36 +13,83 @@ import 'package:path/path.dart' as path; import 'cross_file_darwin_apis.g.dart'; import 'security_scoped_resource.dart'; +/// Base implementation of [PlatformScopedStorageXFileCreationParams] for iOS +/// and macOS. +sealed class DarwinScopedStorageXFileCreationParams + extends PlatformScopedStorageXFileCreationParams { + /// Constructs a [DarwinScopedStorageXFileCreationParams]. + const DarwinScopedStorageXFileCreationParams({required super.uri}); + + /// Constructs a [DarwinScopedStorageXFileCreationParams] with a security + /// scoped uri. + factory DarwinScopedStorageXFileCreationParams.securityScoped({ + required String uri, + @visibleForTesting CrossFileDarwinApi? api, + }) => + SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri, api: api); + + /// Constructs a [DarwinScopedStorageXFileCreationParams] with a security + /// scoped uri. + factory DarwinScopedStorageXFileCreationParams.photoKit({ + required String localIdentifier, + @visibleForTesting CrossFileDarwinApi? api, + }) => PhotoKitDarwinScopedStorageXFileCreationParams( + localIdentifier: localIdentifier, + ); +} + /// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and /// macOS. @immutable -base class DarwinScopedStorageXFileCreationParams - extends PlatformScopedStorageXFileCreationParams { - /// Constructs a [DarwinScopedStorageXFileCreationParams]. - DarwinScopedStorageXFileCreationParams({ +base class SecurityScopedDarwinScopedStorageXFileCreationParams + extends DarwinScopedStorageXFileCreationParams { + /// Constructs a [SecurityScopedDarwinScopedStorageXFileCreationParams]. + SecurityScopedDarwinScopedStorageXFileCreationParams({ required super.uri, @visibleForTesting CrossFileDarwinApi? api, }) : api = api ?? CrossFileDarwinApi(); - /// Constructs an [DarwinScopedStorageXFileCreationParams] from a - /// [PlatformScopedStorageXFileCreationParams]. - factory DarwinScopedStorageXFileCreationParams.fromCreationParams( - PlatformXFileCreationParams params, { - @visibleForTesting CrossFileDarwinApi? api, - }) { - return DarwinScopedStorageXFileCreationParams(uri: params.uri, api: api); - } - /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; } +/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and +/// macOS. +@immutable +base class PhotoKitDarwinScopedStorageXFileCreationParams + extends DarwinScopedStorageXFileCreationParams { + /// Constructs a [PhotoKitDarwinScopedStorageXFileCreationParams]. + const PhotoKitDarwinScopedStorageXFileCreationParams({ + required String localIdentifier, + }) : super(uri: localIdentifier); +} + +/// Base implementation of [PlatformScopedStorageXFile] for iOS and macOS. +sealed class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { + factory DarwinScopedStorageXFile( + PlatformScopedStorageXFileCreationParams params, + ) { + return switch (params) { + final SecurityScopedDarwinScopedStorageXFileCreationParams + securityScopedParams => + SecurityScopedDarwinScopedStorageXFile(securityScopedParams), + final PhotoKitDarwinScopedStorageXFileCreationParams photoKitParams => + PhotoKitDarwinScopedStorageXFile(photoKitParams), + _ => SecurityScopedDarwinScopedStorageXFile(params), + }; + } + + @protected + DarwinScopedStorageXFile._(super.params) : super.implementation(); +} + /// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. -base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile - with DarwinScopedStorageXFileExtension { - /// Constructs a [DarwinScopedStorageXFile]. - DarwinScopedStorageXFile(super.params) : super.implementation() { +base class SecurityScopedDarwinScopedStorageXFile + extends DarwinScopedStorageXFile + with SecurityScopedDarwinScopedStorageXFileExtension { + /// Constructs a [SecurityScopedDarwinScopedStorageXFile]. + SecurityScopedDarwinScopedStorageXFile(super.params) : super._() { _finalizer.attach(this, params.uri); } @@ -56,13 +103,13 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile late final _file = File.fromUri(Uri.parse(params.uri)); @override - late final DarwinScopedStorageXFileCreationParams params = - super.params is DarwinScopedStorageXFileCreationParams - ? super.params as DarwinScopedStorageXFileCreationParams - : DarwinScopedStorageXFileCreationParams.fromCreationParams(super.params); + late final SecurityScopedDarwinScopedStorageXFileCreationParams params = + super.params is SecurityScopedDarwinScopedStorageXFileCreationParams + ? super.params as SecurityScopedDarwinScopedStorageXFileCreationParams + : SecurityScopedDarwinScopedStorageXFileCreationParams(uri: params.uri); @override - DarwinScopedStorageXFileExtension? get extension => this; + SecurityScopedDarwinScopedStorageXFileExtension? get extension => this; @override Future lastModified() async { @@ -115,6 +162,66 @@ base class DarwinScopedStorageXFile extends PlatformScopedStorageXFile } } -/// Provides platform specific features for [DarwinScopedStorageXFile]. -mixin DarwinScopedStorageXFileExtension +/// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. +base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile + with PhotoKitDarwinScopedStorageXFileExtension { + /// Constructs a [SecurityScopedDarwinScopedStorageXFile]. + PhotoKitDarwinScopedStorageXFile(super.params) : super._(); + + @override + late final PhotoKitDarwinScopedStorageXFileCreationParams params = + super.params is PhotoKitDarwinScopedStorageXFileCreationParams + ? super.params as PhotoKitDarwinScopedStorageXFileCreationParams + : PhotoKitDarwinScopedStorageXFileCreationParams( + localIdentifier: params.uri, + ); + + @override + PhotoKitDarwinScopedStorageXFileExtension? get extension => this; + + @override + Future lastModified() async { + throw UnsupportedError(''); + } + + @override + Future length() async { + try { + throw UnsupportedError(''); + } on FileSystemException { + return null; + } + } + + @override + Stream openRead([int? start, int? end]) => + throw UnsupportedError(''); + + @override + Future readAsBytes() => throw UnsupportedError(''); + + @override + Future readAsString({Encoding encoding = utf8}) => + throw UnsupportedError(''); + + @override + Future canRead() { + throw UnsupportedError(''); + } + + @override + Future exists() async => throw UnsupportedError(''); + + @override + Future name() async => throw UnsupportedError(''); +} + +/// Provides platform specific features for +/// [SecurityScopedDarwinScopedStorageXFile]. +mixin SecurityScopedDarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension, SecurityScopedResource {} + +/// Provides platform specific features for +/// [SecurityScopedDarwinScopedStorageXFile]. +mixin PhotoKitDarwinScopedStorageXFileExtension + implements PlatformScopedStorageXFileExtension {} From ef08bac30cbfe3a1be71adc5630d12f280dfe461 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 7 May 2026 13:25:10 -0400 Subject: [PATCH 256/398] darwin api stuffc --- .../CrossFileDarwinApis.g.swift | 97 +++++++++- .../lib/src/cross_file_darwin_apis.g.dart | 179 +++++++++++++----- .../src/darwin_scoped_storage_cross_file.dart | 11 +- .../pigeons/cross_file_darwin_apis.dart | 27 +++ 4 files changed, 258 insertions(+), 56 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 539e2eb56909..ae31a50d1e5a 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.7), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon import Foundation @@ -53,7 +53,7 @@ private func wrapError(_ error: Any) -> [Any?] { } return [ "\(error)", - "\(type(of: error))", + "\(Swift.type(of: error))", "Stacktrace: \(Thread.callStackSymbols)", ] } @@ -100,6 +100,26 @@ protocol CrossFileDarwinApi { func stopAccessingSecurityScopedResource(url: String) throws /// Whether the native FileManager is able to read a specified file. func isReadableFile(url: String) throws -> Bool + /// Date and time when the resource was last modified, if the information is + /// available. + /// + /// Returns null if file doesn't exist or information is not available. + func lastModified(identifier: String, completion: @escaping (Result) -> Void) + /// The length of the data represented by this uri, in bytes. + /// + /// Returns null if file doesn't exist or information is not available. + /// Reads the entire resource contents as a list of bytes. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. + func readAsBytes( + identifier: String, completion: @escaping (Result) -> Void) + /// The name of the resource represented by this object. + /// + /// The path is excluded from this value. + /// + /// Returns null if file doesn't exist or information is not available. + func name(identifier: String, completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. @@ -170,5 +190,78 @@ class CrossFileDarwinApiSetup { } else { isReadableFileChannel.setMessageHandler(nil) } + /// Date and time when the resource was last modified, if the information is + /// available. + /// + /// Returns null if file doesn't exist or information is not available. + let lastModifiedChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.lastModified\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + lastModifiedChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! String + api.lastModified(identifier: identifierArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + lastModifiedChannel.setMessageHandler(nil) + } + /// The length of the data represented by this uri, in bytes. + /// + /// Returns null if file doesn't exist or information is not available. + /// Reads the entire resource contents as a list of bytes. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. + let readAsBytesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.readAsBytes\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + readAsBytesChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! String + api.readAsBytes(identifier: identifierArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + readAsBytesChannel.setMessageHandler(nil) + } + /// The name of the resource represented by this object. + /// + /// The path is excluded from this value. + /// + /// Returns null if file doesn't exist or information is not available. + let nameChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.name\(channelSuffix)", + binaryMessenger: binaryMessenger, codec: codec) + if let api = api { + nameChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! String + api.name(identifier: identifierArg) { result in + switch result { + case .success(let res): + reply(wrapResult(res)) + case .failure(let error): + reply(wrapError(error)) + } + } + } + } else { + nameChannel.setMessageHandler(nil) + } } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 68ff99b92971..829398a4cf2f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -1,21 +1,40 @@ // Copyright 2013 The Flutter Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Autogenerated from Pigeon (v26.1.7), do not edit directly. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. // See also: https://pub.dev/packages/pigeon -// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, omit_obvious_local_variable_types, unused_shown_name, unnecessary_import, no_leading_underscores_for_local_identifiers +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; +import 'dart:typed_data' show Float64List, Int32List, Int64List; -import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -PlatformException _createConnectionError(String channelName) { - return PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; } class _PigeonCodec extends StandardMessageCodec { @@ -71,22 +90,13 @@ class CrossFileDarwinApi { [url], ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; } /// In an app that adopts App Sandbox, revokes access to the resource pointed @@ -103,17 +113,12 @@ class CrossFileDarwinApi { [url], ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else { - return; - } + + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Whether the native FileManager is able to read a specified file. @@ -129,21 +134,91 @@ class CrossFileDarwinApi { [url], ); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - if (pigeonVar_replyList == null) { - throw _createConnectionError(pigeonVar_channelName); - } else if (pigeonVar_replyList.length > 1) { - throw PlatformException( - code: pigeonVar_replyList[0]! as String, - message: pigeonVar_replyList[1] as String?, - details: pigeonVar_replyList[2], - ); - } else if (pigeonVar_replyList[0] == null) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } else { - return (pigeonVar_replyList[0] as bool?)!; - } + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; + } + + /// Date and time when the resource was last modified, if the information is + /// available. + /// + /// Returns null if file doesn't exist or information is not available. + Future lastModified(String identifier) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.lastModified$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue as int?; + } + + /// The length of the data represented by this uri, in bytes. + /// + /// Returns null if file doesn't exist or information is not available. + /// Reads the entire resource contents as a list of bytes. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. + Future readAsBytes(String identifier) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.readAsBytes$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as Uint8List; + } + + /// The name of the resource represented by this object. + /// + /// The path is excluded from this value. + /// + /// Returns null if file doesn't exist or information is not available. + Future name(String identifier) async { + final pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.name$pigeonVar_messageChannelSuffix'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [identifier], + ); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); + return pigeonVar_replyValue as String?; } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 222f66134bb4..1487a9866004 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -35,6 +35,7 @@ sealed class DarwinScopedStorageXFileCreationParams @visibleForTesting CrossFileDarwinApi? api, }) => PhotoKitDarwinScopedStorageXFileCreationParams( localIdentifier: localIdentifier, + api: api, ); } @@ -60,9 +61,15 @@ base class SecurityScopedDarwinScopedStorageXFileCreationParams base class PhotoKitDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { /// Constructs a [PhotoKitDarwinScopedStorageXFileCreationParams]. - const PhotoKitDarwinScopedStorageXFileCreationParams({ + PhotoKitDarwinScopedStorageXFileCreationParams({ required String localIdentifier, - }) : super(uri: localIdentifier); + @visibleForTesting CrossFileDarwinApi? api, + }) : api = api ?? CrossFileDarwinApi(), + super(uri: localIdentifier); + + /// The API used to call to native code to interact with files. + @visibleForTesting + final CrossFileDarwinApi api; } /// Base implementation of [PlatformScopedStorageXFile] for iOS and macOS. diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index f181ee9742cf..f6c233004999 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -27,4 +27,31 @@ abstract class CrossFileDarwinApi { /// Whether the native FileManager is able to read a specified file. bool isReadableFile(String url); + + /// Date and time when the resource was last modified, if the information is + /// available. + /// + /// Returns null if file doesn't exist or information is not available. + @async + int? lastModified(String identifier); + + /// The length of the data represented by this uri, in bytes. + /// + /// Returns null if file doesn't exist or information is not available. + //Future length(String identifier); + + /// Reads the entire resource contents as a list of bytes. + /// + /// Platforms may throw an exception if there is an error opening or reading + /// the resource. + @async + Uint8List readAsBytes(String identifier); + + /// The name of the resource represented by this object. + /// + /// The path is excluded from this value. + /// + /// Returns null if file doesn't exist or information is not available. + @async + String? name(String identifier); } From 4c3428661a497a1c5d20c896a2496c2056416a83 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 7 May 2026 14:04:52 -0400 Subject: [PATCH 257/398] partial impl for darwin --- .../CrossFileDarwinApiImpl.swift | 49 ++++ .../cross_file_darwin/example/lib/main.dart | 229 +++++++++--------- .../cross_file_darwin/example/pubspec.yaml | 39 +-- 3 files changed, 187 insertions(+), 130 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 7c394045cbd0..701aefd475ef 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -3,6 +3,7 @@ // found in the LICENSE file. import Foundation +import Photos #if os(iOS) import Flutter @@ -25,4 +26,52 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { func isReadableFile(url: String) throws -> Bool { return FileManager.default.isReadableFile(atPath: URL(string: url)!.path) } + + func lastModified(identifier: String, completion: @escaping (Result) -> Void) { + let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) + if let asset = fetchResult.firstObject { + if let modificationDate = asset.modificationDate { + completion(.success(Int64(asset.modificationDate.timeIntervalSince1970 * 1000.0).rounded())) + } else { + completion(.success(nil)) + } + } else { + completion(.success(nil)) + } + } + + func readAsBytes( + identifier: String, completion: @escaping (Result) -> Void + ) { + let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) + if let asset = fetchResult.firstObject { + // 3. Request the actual image data from the asset + let manager = PHImageManager.default() + let options = PHImageRequestOptions() + options.isNetworkAccessAllowed = true // In case it's stored in iCloud + + manager.requestImageDataAndOrientation( + for: asset, options: options, + ) { imageData, orientation, info in + + if let imageData = image { + completion(.success(FlutterStandardTypedData(bytes: imageData))) + } else { + completion(.success(nil)) + } + } + } else { + completion(.success(nil)) + } + } + + func name(identifier: String, completion: @escaping (Result) -> Void) { + let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) + if let asset = fetchResult.firstObject { + let resources = PHAssetResource.assetResources(for: asset) + completion(.success(resources.first!.originalFilename)) + } else { + completion(.success(nil)) + } + } } diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 4c4f58a8a56c..e8bffed29aff 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:file_selector/file_selector.dart'; +//import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -15,122 +15,123 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); - - if (file case final XFile file) { - final String filename = await file.name() ?? file.uri; - - switch (mime.lookupMimeType(filename)) { - case final String mimeType when mimeType.startsWith('text'): - final String fileContents = await file.readAsString(); - if (context.mounted) { - await showDialog( - context: context, - builder: (BuildContext context) => - TextDisplay(filename: filename, fileContents: fileContents), - ); - } - case _: - debugPrint('File Uri: ${file.uri}'); - debugPrint('Filename: $filename'); - if (file is ScopedStorageXFile) { - debugPrint('Can Read File: ${await file.canRead()}'); - } - debugPrint('File Length: ${await file.length()}'); - debugPrint('File Last Modified: ${await file.lastModified()}'); - return; - } - } else { - debugPrint('No file selected.'); - } - } - - Future _openDirectory() async { - final XDirectory? directory = await getDirectoryPath(); - - if (directory != null) { - debugPrint('Directory Uri: ${directory.uri}'); - debugPrint('Directory exists: ${await directory.exists()}'); - - debugPrint('List of Entities:'); - await for (final XEntity entity in directory.list()) { - switch (entity) { - case final XFile file: - final String filename = await file.name() ?? file.uri; - debugPrint('\tFile: $filename'); - debugPrint('\t\tFile Length: ${await file.length()}'); - case final XDirectory directory: - debugPrint('\tDirectory: ${directory.uri}'); - } - } - } else { - debugPrint('No directory selected.'); - } - } + // Future _openFile(BuildContext context) async { + // final XFile? file = await openFile(); + // + // if (file case final XFile file) { + // final String filename = await file.name() ?? file.uri; + // + // switch (mime.lookupMimeType(filename)) { + // case final String mimeType when mimeType.startsWith('text'): + // final String fileContents = await file.readAsString(); + // if (context.mounted) { + // await showDialog( + // context: context, + // builder: (BuildContext context) => + // TextDisplay(filename: filename, fileContents: fileContents), + // ); + // } + // case _: + // debugPrint('File Uri: ${file.uri}'); + // debugPrint('Filename: $filename'); + // if (file is ScopedStorageXFile) { + // debugPrint('Can Read File: ${await file.canRead()}'); + // } + // debugPrint('File Length: ${await file.length()}'); + // debugPrint('File Last Modified: ${await file.lastModified()}'); + // return; + // } + // } else { + // debugPrint('No file selected.'); + // } + // } + // + // Future _openDirectory() async { + // final XDirectory? directory = await getDirectoryPath(); + // + // if (directory != null) { + // debugPrint('Directory Uri: ${directory.uri}'); + // debugPrint('Directory exists: ${await directory.exists()}'); + // + // debugPrint('List of Entities:'); + // await for (final XEntity entity in directory.list()) { + // switch (entity) { + // case final XFile file: + // final String filename = await file.name() ?? file.uri; + // debugPrint('\tFile: $filename'); + // debugPrint('\t\tFile Length: ${await file.length()}'); + // case final XDirectory directory: + // debugPrint('\tDirectory: ${directory.uri}'); + // } + // } + // } else { + // debugPrint('No directory selected.'); + // } + // } @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.blue, - backgroundColor: Colors.white, - ), - child: const Text('Open File'), - onPressed: () => _openFile(context), - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.blue, - backgroundColor: Colors.white, - ), - child: const Text('Open Directory'), - onPressed: () => _openDirectory(), - ), - ], - ), - ), - ); + return Container(); + // return Scaffold( + // appBar: AppBar( + // title: const Text('Open a File'), + // backgroundColor: Colors.blue, + // ), + // body: Center( + // child: Column( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // foregroundColor: Colors.blue, + // backgroundColor: Colors.white, + // ), + // child: const Text('Open File'), + // onPressed: () => _openFile(context), + // ), + // ElevatedButton( + // style: ElevatedButton.styleFrom( + // foregroundColor: Colors.blue, + // backgroundColor: Colors.white, + // ), + // child: const Text('Open Directory'), + // onPressed: () => _openDirectory(), + // ), + // ], + // ), + // ), + // ); } } -/// Widget that displays a text file in a dialog. -class TextDisplay extends StatelessWidget { - /// Default Constructor. - const TextDisplay({ - super.key, - required this.filename, - required this.fileContents, - }); - - /// The name of the file. - final String filename; - - /// The contents of the file. - final String fileContents; - - @override - Widget build(BuildContext context) { - return AlertDialog( - title: Text(filename), - content: Scrollbar( - child: SingleChildScrollView(child: Text(fileContents)), - ), - actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), - ], - ); - } -} +// /// Widget that displays a text file in a dialog. +// class TextDisplay extends StatelessWidget { +// /// Default Constructor. +// const TextDisplay({ +// super.key, +// required this.filename, +// required this.fileContents, +// }); +// +// /// The name of the file. +// final String filename; +// +// /// The contents of the file. +// final String fileContents; +// +// @override +// Widget build(BuildContext context) { +// return AlertDialog( +// title: Text(filename), +// content: Scrollbar( +// child: SingleChildScrollView(child: Text(fileContents)), +// ), +// actions: [ +// TextButton( +// child: const Text('Close'), +// onPressed: () => Navigator.pop(context), +// ), +// ], +// ); +// } +// } diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 7998440d3be6..cf02f747390c 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -8,11 +8,18 @@ environment: dependencies: cupertino_icons: ^1.0.8 - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector + cross_file_darwin: + # When depending on this package from a real application you should use: + # cross_file_darwin: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ +# file_selector: +# git: +# url: https://github.com/bparrishMines/packages +# ref: new_file_selector +# path: packages/file_selector/file_selector flutter: sdk: flutter mime: ^2.0.0 @@ -28,14 +35,14 @@ flutter: assets: - assets/hello.txt -dependency_overrides: - # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because - # the updated file_selector branch depends on cross_file_darwin from git and this overrides its - # dependency. - cross_file_darwin: - # When depending on this package from a real application you should use: - # cross_file_darwin: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ \ No newline at end of file +#dependency_overrides: +# # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because +# # the updated file_selector branch depends on cross_file_darwin from git and this overrides its +# # dependency. +# cross_file_darwin: +# # When depending on this package from a real application you should use: +# # cross_file_darwin: ^x.y.z +# # See https://dart.dev/tools/pub/dependencies#version-constraints +# # The example app is bundled with the plugin so we use a path dependency on +# # the parent directory to use the current plugin's version. +# path: ../ \ No newline at end of file From df66b0255bf552a1ef078b6cc3295a79bc1860bf Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 27 May 2026 18:00:46 -0400 Subject: [PATCH 258/398] update pubspec sdk versions --- packages/cross_file/cross_file/example/pubspec.yaml | 2 +- packages/cross_file/cross_file/pubspec.yaml | 2 +- packages/cross_file/cross_file_android/example/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_android/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_darwin/example/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_darwin/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_io/example/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_io/pubspec.yaml | 4 ++-- .../cross_file/cross_file_platform_interface/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_web/example/pubspec.yaml | 4 ++-- packages/cross_file/cross_file_web/pubspec.yaml | 4 ++-- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index 62234c2eb5b1..1a6cba1cd7e3 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -4,7 +4,7 @@ publish_to: none environment: sdk: ^3.10.0 - flutter: ">=3.35.0" + flutter: ">=3.38.0" dependencies: cross_file: diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index 2606b3ef8e7e..b4cd825ef03a 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -7,7 +7,7 @@ publish_to: none environment: sdk: ^3.10.0 - flutter: ">=3.35.0" + flutter: ">=3.38.0" flutter: plugin: diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index f6f3935299ce..f565d6ccf85f 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -3,8 +3,8 @@ description: "Demonstrates how to use the cross_file_android plugin." publish_to: 'none' environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" dependencies: file_selector: diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 4c06d9e2f1d1..6eefc3dc80a9 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -6,8 +6,8 @@ version: 0.1.0 publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" flutter: plugin: diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index cf02f747390c..3f486beb1278 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -3,8 +3,8 @@ description: "Demonstrates how to use the cross_file_darwin plugin." publish_to: 'none' environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" dependencies: cupertino_icons: ^1.0.8 diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 7fbaac357410..7c7aeafad42c 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -6,8 +6,8 @@ version: 0.1.0 publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" flutter: plugin: diff --git a/packages/cross_file/cross_file_io/example/pubspec.yaml b/packages/cross_file/cross_file_io/example/pubspec.yaml index f956a0466c67..c5a2615988c7 100644 --- a/packages/cross_file/cross_file_io/example/pubspec.yaml +++ b/packages/cross_file/cross_file_io/example/pubspec.yaml @@ -3,8 +3,8 @@ description: Demonstrates how to use cross files. publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" dependencies: cross_file: diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index b2e3dbc33011..a3be39e13e97 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -6,8 +6,8 @@ version: 0.1.0 publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" flutter: plugin: diff --git a/packages/cross_file/cross_file_platform_interface/pubspec.yaml b/packages/cross_file/cross_file_platform_interface/pubspec.yaml index 545a8924b67f..dacb6c7ca3d2 100644 --- a/packages/cross_file/cross_file_platform_interface/pubspec.yaml +++ b/packages/cross_file/cross_file_platform_interface/pubspec.yaml @@ -8,8 +8,8 @@ version: 0.1.0 publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" dependencies: flutter: diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index f0dba25d5205..6a673fcbf740 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -2,8 +2,8 @@ name: cross_file_web_example publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" dependencies: file_selector: diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index a7b80149c293..0ead2be5996b 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -6,8 +6,8 @@ version: 0.1.0 publish_to: none environment: - sdk: ^3.9.0 - flutter: ">=3.35.0" + sdk: ^3.10.0 + flutter: ">=3.38.0" flutter: plugin: From c1c066f556ce6c2f535520c9a05b4e7b1a497e3a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 29 May 2026 10:35:50 -0400 Subject: [PATCH 259/398] update darwin xfile docs --- .../lib/cross_file_darwin.dart | 3 ++- .../src/darwin_scoped_storage_cross_file.dart | 18 +++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index aa69e55089dd..feda698cae93 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -17,5 +17,6 @@ export 'src/darwin_scoped_storage_cross_directory.dart' export 'src/darwin_scoped_storage_cross_file.dart' show DarwinScopedStorageXFileCreationParams, - DarwinScopedStorageXFileExtension; + PhotoKitDarwinScopedStorageXFileExtension, + SecurityScopedDarwinScopedStorageXFileExtension; export 'src/security_scoped_resource.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 1487a9866004..7ef0d166d9ee 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -28,8 +28,8 @@ sealed class DarwinScopedStorageXFileCreationParams }) => SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri, api: api); - /// Constructs a [DarwinScopedStorageXFileCreationParams] with a security - /// scoped uri. + /// Constructs a [DarwinScopedStorageXFileCreationParams] with an asset + /// identifier from the Photos Library. factory DarwinScopedStorageXFileCreationParams.photoKit({ required String localIdentifier, @visibleForTesting CrossFileDarwinApi? api, @@ -39,8 +39,7 @@ sealed class DarwinScopedStorageXFileCreationParams ); } -/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and -/// macOS. +/// Creation parameters for [SecurityScopedDarwinScopedStorageXFile]. @immutable base class SecurityScopedDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { @@ -55,8 +54,7 @@ base class SecurityScopedDarwinScopedStorageXFileCreationParams final CrossFileDarwinApi api; } -/// Implementation of [PlatformScopedStorageXFileCreationParams] for iOS and -/// macOS. +/// Creation parameters for [PhotoKitDarwinScopedStorageXFile]. @immutable base class PhotoKitDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { @@ -91,7 +89,8 @@ sealed class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { DarwinScopedStorageXFile._(super.params) : super.implementation(); } -/// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. +/// Implementation of [DarwinScopedStorageXFile] for interacting with a +/// security-scoped URL. base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFile with SecurityScopedDarwinScopedStorageXFileExtension { @@ -169,7 +168,8 @@ base class SecurityScopedDarwinScopedStorageXFile } } -/// Implementation of [PlatformScopedStorageXFile] for iOS and macOS. +/// Implementation of [DarwinScopedStorageXFile] as a representation of a +/// image, video, or Live Photo in the Photos library. base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile with PhotoKitDarwinScopedStorageXFileExtension { /// Constructs a [SecurityScopedDarwinScopedStorageXFile]. @@ -229,6 +229,6 @@ mixin SecurityScopedDarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension, SecurityScopedResource {} /// Provides platform specific features for -/// [SecurityScopedDarwinScopedStorageXFile]. +/// [PhotoKitDarwinScopedStorageXFile]. mixin PhotoKitDarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension {} From 3d9f91e1c20718a1a3dd54d49f01ee9d82a0909f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 29 May 2026 11:04:32 -0400 Subject: [PATCH 260/398] update directory to be similar to file --- .../lib/cross_file_darwin.dart | 2 +- ...darwin_scoped_storage_cross_directory.dart | 79 ++++++++++++------- .../src/darwin_scoped_storage_cross_file.dart | 6 +- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index feda698cae93..6c2deb751b80 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -13,7 +13,7 @@ export 'src/cross_file_darwin.dart'; export 'src/darwin_scoped_storage_cross_directory.dart' show DarwinScopedStorageXDirectoryCreationParams, - DarwinScopedStorageXDirectoryExtension; + SecurityScopedDarwinScopedStorageXDirectoryExtension; export 'src/darwin_scoped_storage_cross_file.dart' show DarwinScopedStorageXFileCreationParams, diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index b789d423178f..744cf9c37a64 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -15,36 +15,57 @@ import 'security_scoped_resource.dart'; /// Implementation of [PlatformScopedStorageXDirectoryCreationParams] for iOS /// and macOS. @immutable -base class DarwinScopedStorageXDirectoryCreationParams +sealed class DarwinScopedStorageXDirectoryCreationParams extends PlatformScopedStorageXDirectoryCreationParams { /// Constructs a [DarwinScopedStorageXDirectoryCreationParams]. - DarwinScopedStorageXDirectoryCreationParams({ - required super.uri, + const DarwinScopedStorageXDirectoryCreationParams({required super.uri}); + + /// Constructs a [DarwinScopedStorageXDirectoryCreationParams] with a security + /// scoped uri. + factory DarwinScopedStorageXDirectoryCreationParams.securityScoped({ + required String uri, @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(); + }) => SecurityScopedDarwinScopedStorageXDirectoryCreationParams( + uri: uri, + api: api, + ); +} - /// Constructs an [DarwinScopedStorageXDirectoryCreationParams] from a - /// [PlatformScopedStorageXDirectoryCreationParams]. - factory DarwinScopedStorageXDirectoryCreationParams.fromCreationParams( - PlatformScopedStorageXDirectoryCreationParams params, { +/// Creation parameters for [SecurityScopedDarwinScopedStorageXDirectory]. +@immutable +base class SecurityScopedDarwinScopedStorageXDirectoryCreationParams + extends DarwinScopedStorageXDirectoryCreationParams { + /// Constructs a [SecurityScopedDarwinScopedStorageXDirectoryCreationParams]. + SecurityScopedDarwinScopedStorageXDirectoryCreationParams({ + required super.uri, @visibleForTesting CrossFileDarwinApi? api, - }) { - return DarwinScopedStorageXDirectoryCreationParams( - uri: params.uri, - api: api, - ); - } + }) : api = api ?? CrossFileDarwinApi(); /// The API used to call to native code to interact with files. @visibleForTesting final CrossFileDarwinApi api; } -/// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. -base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory - with DarwinScopedStorageXDirectoryExtension { - /// Constructs a [DarwinScopedStorageXDirectory]. - DarwinScopedStorageXDirectory(super.params) : super.implementation() { +/// Base implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. +sealed class DarwinScopedStorageXDirectory + extends PlatformScopedStorageXDirectory { + factory DarwinScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams params, + ) { + return SecurityScopedDarwinScopedStorageXDirectory(params); + } + + @protected + DarwinScopedStorageXDirectory._(super.params) : super.implementation(); +} + +/// Implementation of [DarwinScopedStorageXDirectory] for interacting with a +/// security-scoped URL. +base class SecurityScopedDarwinScopedStorageXDirectory + extends DarwinScopedStorageXDirectory + with SecurityScopedDarwinScopedStorageXDirectoryExtension { + /// Constructs a [SecurityScopedDarwinScopedStorageXDirectory]. + SecurityScopedDarwinScopedStorageXDirectory(super.params) : super._() { _finalizer.attach(this, params.uri); } @@ -58,15 +79,16 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory late final _directory = Directory.fromUri(Uri.parse(params.uri)); @override - late final DarwinScopedStorageXDirectoryCreationParams params = - super.params is DarwinScopedStorageXDirectoryCreationParams - ? super.params as DarwinScopedStorageXDirectoryCreationParams - : DarwinScopedStorageXDirectoryCreationParams.fromCreationParams( - super.params, + late final SecurityScopedDarwinScopedStorageXDirectoryCreationParams params = + super.params is SecurityScopedDarwinScopedStorageXDirectoryCreationParams + ? super.params + as SecurityScopedDarwinScopedStorageXDirectoryCreationParams + : SecurityScopedDarwinScopedStorageXDirectoryCreationParams( + uri: super.params.uri, ); @override - DarwinScopedStorageXDirectoryExtension? get extension => this; + SecurityScopedDarwinScopedStorageXDirectoryExtension? get extension => this; @override Future exists() async => _directory.existsSync(); @@ -77,7 +99,7 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory switch (entity) { case final Directory directory: yield DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams( + DarwinScopedStorageXDirectoryCreationParams.securityScoped( uri: directory.uri.toString(), ), ); @@ -107,8 +129,9 @@ base class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory } } -/// Provides platform specific features for [DarwinScopedStorageXDirectory]. -mixin DarwinScopedStorageXDirectoryExtension +/// Provides platform specific features for +/// [SecurityScopedDarwinScopedStorageXDirectory]. +mixin SecurityScopedDarwinScopedStorageXDirectoryExtension implements PlatformScopedStorageXDirectoryExtension, SecurityScopedResource {} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 7ef0d166d9ee..7e95d3324a0a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -112,7 +112,9 @@ base class SecurityScopedDarwinScopedStorageXFile late final SecurityScopedDarwinScopedStorageXFileCreationParams params = super.params is SecurityScopedDarwinScopedStorageXFileCreationParams ? super.params as SecurityScopedDarwinScopedStorageXFileCreationParams - : SecurityScopedDarwinScopedStorageXFileCreationParams(uri: params.uri); + : SecurityScopedDarwinScopedStorageXFileCreationParams( + uri: super.params.uri, + ); @override SecurityScopedDarwinScopedStorageXFileExtension? get extension => this; @@ -180,7 +182,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile super.params is PhotoKitDarwinScopedStorageXFileCreationParams ? super.params as PhotoKitDarwinScopedStorageXFileCreationParams : PhotoKitDarwinScopedStorageXFileCreationParams( - localIdentifier: params.uri, + localIdentifier: super.params.uri, ); @override From a408ce9aadf8cf5eb2acc9554d787ad15453d1bf Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 29 May 2026 14:47:27 -0400 Subject: [PATCH 261/398] add ffi to pubspec --- packages/cross_file/cross_file_darwin/pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 7c7aeafad42c..5d717163ed43 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -33,12 +33,15 @@ dependencies: url: https://github.com/bparrishMines/packages ref: new_crossfile path: packages/cross_file/cross_file_platform_interface + ffi: ^2.2.0 flutter: sdk: flutter + objective_c: ^9.4.1 path: ^1.9.1 dev_dependencies: build_runner: ^2.10.4 + ffigen: ^20.1.1 flutter_test: sdk: flutter mockito: ^5.4.4 From 71f72fe9490532fd1504e4222bfc2fd848b65118 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:11:29 -0400 Subject: [PATCH 262/398] update for ffigen --- .../lib/src/cross_file_darwin.dart | 11 ++ .../src/darwin_scoped_storage_cross_file.dart | 23 ++- .../lib/src/ffi_bindings.g.dart | 153 ++++++++++++++++++ .../cross_file_darwin/tool/ffigen.dart | 79 +++++++++ 4 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart create mode 100644 packages/cross_file/cross_file_darwin/tool/ffigen.dart diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index e68261025156..53b21ab67924 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -33,3 +33,14 @@ base class CrossFileDarwin extends CrossFileIO { return DarwinScopedStorageXDirectory(params); } } + +// final ffi.DynamicLibrary _dylib = () { +// return ffi.DynamicLibrary.open( +// '/System/Library/Frameworks/Foundation.framework/Foundation', +// ); +// }(); + +// /// The bindings to the native functions in [_dylib]. +// final FoundationFFI _lib = () { +// return FoundationFFI(_dylib); +// }(); diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 7e95d3324a0a..5c9cf04e4adb 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -4,8 +4,11 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:ffi' as ffi; import 'dart:io'; +import 'package:objective_c/objective_c.dart'; + import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; import 'package:path/path.dart' as path; @@ -13,6 +16,8 @@ import 'package:path/path.dart' as path; import 'cross_file_darwin_apis.g.dart'; import 'security_scoped_resource.dart'; +import 'ffi_bindings.g.dart'; + /// Base implementation of [PlatformScopedStorageXFileCreationParams] for iOS /// and macOS. sealed class DarwinScopedStorageXFileCreationParams @@ -160,13 +165,23 @@ base class SecurityScopedDarwinScopedStorageXFile Future name() async => path.basename(_file.path); @override - Future startAccessingSecurityScopedResource() { - return params.api.startAccessingSecurityScopedResource(params.uri); + Future startAccessingSecurityScopedResource() async { + final NSURL? url = NSURL.URLWithString(NSString(params.uri)); + if (url == null) { + return false; + } + return url.startAccessingSecurityScopedResource(); + //return params.api.startAccessingSecurityScopedResource(params.uri); } @override - Future stopAccessingSecurityScopedResource() { - return params.api.stopAccessingSecurityScopedResource(params.uri); + Future stopAccessingSecurityScopedResource() async { + final NSURL? url = NSURL.URLWithString(NSString(params.uri)); + if (url != null) { + url.stopAccessingSecurityScopedResource(); + } + //return url.stopAccessingSecurityScopedResource(); + //return params.api.stopAccessingSecurityScopedResource(params.uri); } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart new file mode 100644 index 000000000000..94f9cab08770 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -0,0 +1,153 @@ +// AUTO GENERATED FILE, DO NOT EDIT. +// +// Generated by `package:ffigen`. +// ignore_for_file: type=lint, unused_import +import 'dart:ffi' as ffi; +import 'package:objective_c/objective_c.dart' as objc; +import 'package:ffi/ffi.dart' as pkg_ffi; + +late final _class_NSFileManager = objc.getClass("NSFileManager"); +late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:"); +final _objc_msgSend_19nvye5 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_isReadableFileAtPath_ = objc.registerName( + "isReadableFileAtPath:", +); +late final _sel_homeDirectoryForCurrentUser = objc.registerName( + "homeDirectoryForCurrentUser", +); +final _objc_msgSend_151sglz = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); +late final _sel_homeDirectoryForUser_ = objc.registerName( + "homeDirectoryForUser:", +); +final _objc_msgSend_1sotr3r = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// NSUserInformation +extension NSUserInformation on NSFileManager { + /// homeDirectoryForCurrentUser + objc.NSURL get homeDirectoryForCurrentUser { + objc.checkOsVersionInternal( + 'NSFileManager.homeDirectoryForCurrentUser', + iOS: (true, null), + macOS: (false, (10, 12, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_homeDirectoryForCurrentUser, + ); + return objc.NSURL.fromPointer($ret, retain: true, release: true); + } + + /// homeDirectoryForUser: + objc.NSURL? homeDirectoryForUser(objc.NSString userName) { + objc.checkOsVersionInternal( + 'NSFileManager.homeDirectoryForUser:', + iOS: (true, null), + macOS: (false, (10, 12, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_homeDirectoryForUser_, + userName.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.NSURL.fromPointer($ret, retain: true, release: true); + } + + /// temporaryDirectory + objc.NSURL get temporaryDirectory { + objc.checkOsVersionInternal( + 'NSFileManager.temporaryDirectory', + iOS: (false, (10, 0, 0)), + macOS: (false, (10, 12, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_temporaryDirectory, + ); + return objc.NSURL.fromPointer($ret, retain: true, release: true); + } +} + +/// NSFileManager +extension type NSFileManager._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSFileManager] that points to the same underlying object as [other]. + NSFileManager.as(objc.ObjCObject other) : object$ = other { + assert(isA(object$)); + } + + /// Constructs a [NSFileManager] that wraps the given raw object pointer. + NSFileManager.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [NSFileManager]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_NSFileManager, + ); +} + +extension NSFileManager$Methods on NSFileManager { + /// isReadableFileAtPath: + bool isReadableFileAtPath(objc.NSString path) { + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isReadableFileAtPath_, + path.ref.pointer, + ); + } +} diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart new file mode 100644 index 000000000000..7d24a7fbb07b --- /dev/null +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -0,0 +1,79 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:ffigen/ffigen.dart'; + +void main() { + final Uri packageRoot = Platform.script.resolve('../'); + FfiGenerator( + output: Output( + dartFile: packageRoot.resolve('lib/src/ffi_bindings.g.dart'), + // style: const DynamicLibraryBindings( + // wrapperName: 'FoundationFFI', + // wrapperDocComment: 'Bindings for Photos Library.', + // ), + ), + headers: Headers( + entryPoints: [ + // Uri.file( + // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/Photos.h', + // ), + // Uri.file( + // '$macSdkPath/System/Library/Frameworks/Foundation.framework/Headers/NSFileManager.h', + // ), + Uri.file( + '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAsset.h', + ), + // Uri.file( + // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResource.h', + // ), + // Uri.file( + // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResourceManager.h', + // ), + // Uri.file( + // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHFetchResult.h', + // ), + // Uri.file( + // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHImageManager.h', + // ), + ], + ), + objectiveC: ObjectiveC( + interfaces: Interfaces( + include: (Declaration declaration) { + return { + 'NSFileManager', + // 'PHAsset', + // 'PHAssetResource', + // 'PHAssetResourceManager', + // 'PHFetchResult', + // 'PHImageManager', + }.contains(declaration.originalName); + }, + includeMember: (Declaration declaration, String member) { + final String interfaceName = declaration.originalName; + final signature = member; + return switch (interfaceName) { + 'NSFileManager' => { + 'isReadableFileAtPath:', + }.contains(signature), + _ => false, + }; + }, + ), + // categories: Categories( + // include: (Declaration declaration) => { + // // For URLByAppendingPathComponent: + // 'NSURLPathUtilities', + // }.contains(declaration.originalName), + // includeTransitive: false, + // ), + ), + // functions: Functions.includeSet({ + // 'NSSearchPathForDirectoriesInDomains', + // }), + ).generate(); +} From 01e5d9739365040addf19e477f90a25934c62bcf Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:26:57 -0400 Subject: [PATCH 263/398] fix compilation --- .../CrossFileDarwinApis.g.swift | 117 +------------- .../CrossFileDarwinApiImpl.swift | 96 ++++++------ .../lib/src/cross_file_darwin_apis.g.dart | 145 ++++-------------- .../pigeons/cross_file_darwin_apis.dart | 54 +++---- 4 files changed, 110 insertions(+), 302 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index ae31a50d1e5a..dab17ef13048 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -67,6 +67,7 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } + private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { } @@ -84,8 +85,7 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec( - readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } /// Api for getting access to file information. @@ -100,43 +100,17 @@ protocol CrossFileDarwinApi { func stopAccessingSecurityScopedResource(url: String) throws /// Whether the native FileManager is able to read a specified file. func isReadableFile(url: String) throws -> Bool - /// Date and time when the resource was last modified, if the information is - /// available. - /// - /// Returns null if file doesn't exist or information is not available. - func lastModified(identifier: String, completion: @escaping (Result) -> Void) - /// The length of the data represented by this uri, in bytes. - /// - /// Returns null if file doesn't exist or information is not available. - /// Reads the entire resource contents as a list of bytes. - /// - /// Platforms may throw an exception if there is an error opening or reading - /// the resource. - func readAsBytes( - identifier: String, completion: @escaping (Result) -> Void) - /// The name of the resource represented by this object. - /// - /// The path is excluded from this value. - /// - /// Returns null if file doesn't exist or information is not available. - func name(identifier: String, completion: @escaping (Result) -> Void) } /// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. class CrossFileDarwinApiSetup { static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp( - binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, - messageChannelSuffix: String = "" - ) { + static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -153,10 +127,7 @@ class CrossFileDarwinApiSetup { } /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -172,10 +143,7 @@ class CrossFileDarwinApiSetup { stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) } /// Whether the native FileManager is able to read a specified file. - let isReadableFileChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) + let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) if let api = api { isReadableFileChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -190,78 +158,5 @@ class CrossFileDarwinApiSetup { } else { isReadableFileChannel.setMessageHandler(nil) } - /// Date and time when the resource was last modified, if the information is - /// available. - /// - /// Returns null if file doesn't exist or information is not available. - let lastModifiedChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.lastModified\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - lastModifiedChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! String - api.lastModified(identifier: identifierArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - lastModifiedChannel.setMessageHandler(nil) - } - /// The length of the data represented by this uri, in bytes. - /// - /// Returns null if file doesn't exist or information is not available. - /// Reads the entire resource contents as a list of bytes. - /// - /// Platforms may throw an exception if there is an error opening or reading - /// the resource. - let readAsBytesChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.readAsBytes\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - readAsBytesChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! String - api.readAsBytes(identifier: identifierArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - readAsBytesChannel.setMessageHandler(nil) - } - /// The name of the resource represented by this object. - /// - /// The path is excluded from this value. - /// - /// Returns null if file doesn't exist or information is not available. - let nameChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.name\(channelSuffix)", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - nameChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! String - api.name(identifier: identifierArg) { result in - switch result { - case .success(let res): - reply(wrapResult(res)) - case .failure(let error): - reply(wrapError(error)) - } - } - } - } else { - nameChannel.setMessageHandler(nil) - } } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift index 701aefd475ef..c6b6424b9bd3 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift @@ -26,52 +26,52 @@ class CrossFileDarwinApiImpl: CrossFileDarwinApi { func isReadableFile(url: String) throws -> Bool { return FileManager.default.isReadableFile(atPath: URL(string: url)!.path) } - - func lastModified(identifier: String, completion: @escaping (Result) -> Void) { - let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) - if let asset = fetchResult.firstObject { - if let modificationDate = asset.modificationDate { - completion(.success(Int64(asset.modificationDate.timeIntervalSince1970 * 1000.0).rounded())) - } else { - completion(.success(nil)) - } - } else { - completion(.success(nil)) - } - } - - func readAsBytes( - identifier: String, completion: @escaping (Result) -> Void - ) { - let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) - if let asset = fetchResult.firstObject { - // 3. Request the actual image data from the asset - let manager = PHImageManager.default() - let options = PHImageRequestOptions() - options.isNetworkAccessAllowed = true // In case it's stored in iCloud - - manager.requestImageDataAndOrientation( - for: asset, options: options, - ) { imageData, orientation, info in - - if let imageData = image { - completion(.success(FlutterStandardTypedData(bytes: imageData))) - } else { - completion(.success(nil)) - } - } - } else { - completion(.success(nil)) - } - } - - func name(identifier: String, completion: @escaping (Result) -> Void) { - let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) - if let asset = fetchResult.firstObject { - let resources = PHAssetResource.assetResources(for: asset) - completion(.success(resources.first!.originalFilename)) - } else { - completion(.success(nil)) - } - } + // + // func lastModified(identifier: String, completion: @escaping (Result) -> Void) { + // let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) + // if let asset = fetchResult.firstObject { + // if let modificationDate = asset.modificationDate { + // completion(.success(Int64(asset.modificationDate.timeIntervalSince1970 * 1000.0).rounded())) + // } else { + // completion(.success(nil)) + // } + // } else { + // completion(.success(nil)) + // } + // } + // + // func readAsBytes( + // identifier: String, completion: @escaping (Result) -> Void + // ) { + // let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) + // if let asset = fetchResult.firstObject { + // // 3. Request the actual image data from the asset + // let manager = PHImageManager.default() + // let options = PHImageRequestOptions() + // options.isNetworkAccessAllowed = true // In case it's stored in iCloud + // + // manager.requestImageDataAndOrientation( + // for: asset, options: options, + // ) { imageData, orientation, info in + // + // if let imageData = image { + // completion(.success(FlutterStandardTypedData(bytes: imageData))) + // } else { + // completion(.success(nil)) + // } + // } + // } else { + // completion(.success(nil)) + // } + // } + // + // func name(identifier: String, completion: @escaping (Result) -> Void) { + // let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) + // if let asset = fetchResult.firstObject { + // let resources = PHAssetResource.assetResources(for: asset) + // completion(.success(resources.first!.originalFilename)) + // } else { + // completion(.success(nil)) + // } + // } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 829398a4cf2f..771a38c41383 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -13,9 +13,9 @@ import 'package:flutter/services.dart'; import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, + List? replyList, + String channelName, { + required bool isNullValid, }) { if (replyList == null) { throw PlatformException( @@ -37,6 +37,8 @@ Object? _extractReplyValueOrThrow( return replyList.firstOrNull; } + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -63,13 +65,9 @@ class CrossFileDarwinApi { /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({ - BinaryMessenger? binaryMessenger, - String messageChannelSuffix = '', - }) : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty - ? '.$messageChannelSuffix' - : ''; + CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) + : pigeonVar_binaryMessenger = binaryMessenger, + pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; final BinaryMessenger? pigeonVar_binaryMessenger; static const MessageCodec pigeonChannelCodec = _PigeonCodec(); @@ -79,146 +77,61 @@ class CrossFileDarwinApi { /// In an app that has adopted App Sandbox, makes the resource pointed to by a /// security-scoped URL available to the app. Future startAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ) + ; return pigeonVar_replyValue! as bool; } /// In an app that adopts App Sandbox, revokes access to the resource pointed /// to by a security-scoped URL. Future stopAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ) + ; } /// Whether the native FileManager is able to read a specified file. Future isReadableFile(String url) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; + final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [url], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ); + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ) + ; return pigeonVar_replyValue! as bool; } - - /// Date and time when the resource was last modified, if the information is - /// available. - /// - /// Returns null if file doesn't exist or information is not available. - Future lastModified(String identifier) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.lastModified$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); - return pigeonVar_replyValue as int?; - } - - /// The length of the data represented by this uri, in bytes. - /// - /// Returns null if file doesn't exist or information is not available. - /// Reads the entire resource contents as a list of bytes. - /// - /// Platforms may throw an exception if there is an error opening or reading - /// the resource. - Future readAsBytes(String identifier) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.readAsBytes$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ); - return pigeonVar_replyValue! as Uint8List; - } - - /// The name of the resource represented by this object. - /// - /// The path is excluded from this value. - /// - /// Returns null if file doesn't exist or information is not available. - Future name(String identifier) async { - final pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.name$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); - return pigeonVar_replyValue as String?; - } } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index f6c233004999..fe938f5f0877 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -27,31 +27,31 @@ abstract class CrossFileDarwinApi { /// Whether the native FileManager is able to read a specified file. bool isReadableFile(String url); - - /// Date and time when the resource was last modified, if the information is - /// available. - /// - /// Returns null if file doesn't exist or information is not available. - @async - int? lastModified(String identifier); - - /// The length of the data represented by this uri, in bytes. - /// - /// Returns null if file doesn't exist or information is not available. - //Future length(String identifier); - - /// Reads the entire resource contents as a list of bytes. - /// - /// Platforms may throw an exception if there is an error opening or reading - /// the resource. - @async - Uint8List readAsBytes(String identifier); - - /// The name of the resource represented by this object. - /// - /// The path is excluded from this value. - /// - /// Returns null if file doesn't exist or information is not available. - @async - String? name(String identifier); + // + // /// Date and time when the resource was last modified, if the information is + // /// available. + // /// + // /// Returns null if file doesn't exist or information is not available. + // @async + // int? lastModified(String identifier); + // + // /// The length of the data represented by this uri, in bytes. + // /// + // /// Returns null if file doesn't exist or information is not available. + // //Future length(String identifier); + // + // /// Reads the entire resource contents as a list of bytes. + // /// + // /// Platforms may throw an exception if there is an error opening or reading + // /// the resource. + // @async + // Uint8List readAsBytes(String identifier); + // + // /// The name of the resource represented by this object. + // /// + // /// The path is excluded from this value. + // /// + // /// Returns null if file doesn't exist or information is not available. + // @async + // String? name(String identifier); } From 4f9feb1641540d257db8f6136e75873e046925f0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:50:04 -0400 Subject: [PATCH 264/398] fix example --- .../cross_file_darwin/example/lib/main.dart | 229 +++++++++--------- .../cross_file_darwin/example/pubspec.yaml | 32 +-- 2 files changed, 130 insertions(+), 131 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index e8bffed29aff..4c4f58a8a56c 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -//import 'package:file_selector/file_selector.dart'; +import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -15,123 +15,122 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - // Future _openFile(BuildContext context) async { - // final XFile? file = await openFile(); - // - // if (file case final XFile file) { - // final String filename = await file.name() ?? file.uri; - // - // switch (mime.lookupMimeType(filename)) { - // case final String mimeType when mimeType.startsWith('text'): - // final String fileContents = await file.readAsString(); - // if (context.mounted) { - // await showDialog( - // context: context, - // builder: (BuildContext context) => - // TextDisplay(filename: filename, fileContents: fileContents), - // ); - // } - // case _: - // debugPrint('File Uri: ${file.uri}'); - // debugPrint('Filename: $filename'); - // if (file is ScopedStorageXFile) { - // debugPrint('Can Read File: ${await file.canRead()}'); - // } - // debugPrint('File Length: ${await file.length()}'); - // debugPrint('File Last Modified: ${await file.lastModified()}'); - // return; - // } - // } else { - // debugPrint('No file selected.'); - // } - // } - // - // Future _openDirectory() async { - // final XDirectory? directory = await getDirectoryPath(); - // - // if (directory != null) { - // debugPrint('Directory Uri: ${directory.uri}'); - // debugPrint('Directory exists: ${await directory.exists()}'); - // - // debugPrint('List of Entities:'); - // await for (final XEntity entity in directory.list()) { - // switch (entity) { - // case final XFile file: - // final String filename = await file.name() ?? file.uri; - // debugPrint('\tFile: $filename'); - // debugPrint('\t\tFile Length: ${await file.length()}'); - // case final XDirectory directory: - // debugPrint('\tDirectory: ${directory.uri}'); - // } - // } - // } else { - // debugPrint('No directory selected.'); - // } - // } + Future _openFile(BuildContext context) async { + final XFile? file = await openFile(); + + if (file case final XFile file) { + final String filename = await file.name() ?? file.uri; + + switch (mime.lookupMimeType(filename)) { + case final String mimeType when mimeType.startsWith('text'): + final String fileContents = await file.readAsString(); + if (context.mounted) { + await showDialog( + context: context, + builder: (BuildContext context) => + TextDisplay(filename: filename, fileContents: fileContents), + ); + } + case _: + debugPrint('File Uri: ${file.uri}'); + debugPrint('Filename: $filename'); + if (file is ScopedStorageXFile) { + debugPrint('Can Read File: ${await file.canRead()}'); + } + debugPrint('File Length: ${await file.length()}'); + debugPrint('File Last Modified: ${await file.lastModified()}'); + return; + } + } else { + debugPrint('No file selected.'); + } + } + + Future _openDirectory() async { + final XDirectory? directory = await getDirectoryPath(); + + if (directory != null) { + debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory exists: ${await directory.exists()}'); + + debugPrint('List of Entities:'); + await for (final XEntity entity in directory.list()) { + switch (entity) { + case final XFile file: + final String filename = await file.name() ?? file.uri; + debugPrint('\tFile: $filename'); + debugPrint('\t\tFile Length: ${await file.length()}'); + case final XDirectory directory: + debugPrint('\tDirectory: ${directory.uri}'); + } + } + } else { + debugPrint('No directory selected.'); + } + } @override Widget build(BuildContext context) { - return Container(); - // return Scaffold( - // appBar: AppBar( - // title: const Text('Open a File'), - // backgroundColor: Colors.blue, - // ), - // body: Center( - // child: Column( - // mainAxisAlignment: MainAxisAlignment.center, - // children: [ - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // foregroundColor: Colors.blue, - // backgroundColor: Colors.white, - // ), - // child: const Text('Open File'), - // onPressed: () => _openFile(context), - // ), - // ElevatedButton( - // style: ElevatedButton.styleFrom( - // foregroundColor: Colors.blue, - // backgroundColor: Colors.white, - // ), - // child: const Text('Open Directory'), - // onPressed: () => _openDirectory(), - // ), - // ], - // ), - // ), - // ); + return Scaffold( + appBar: AppBar( + title: const Text('Open a File'), + backgroundColor: Colors.blue, + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open File'), + onPressed: () => _openFile(context), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + foregroundColor: Colors.blue, + backgroundColor: Colors.white, + ), + child: const Text('Open Directory'), + onPressed: () => _openDirectory(), + ), + ], + ), + ), + ); } } -// /// Widget that displays a text file in a dialog. -// class TextDisplay extends StatelessWidget { -// /// Default Constructor. -// const TextDisplay({ -// super.key, -// required this.filename, -// required this.fileContents, -// }); -// -// /// The name of the file. -// final String filename; -// -// /// The contents of the file. -// final String fileContents; -// -// @override -// Widget build(BuildContext context) { -// return AlertDialog( -// title: Text(filename), -// content: Scrollbar( -// child: SingleChildScrollView(child: Text(fileContents)), -// ), -// actions: [ -// TextButton( -// child: const Text('Close'), -// onPressed: () => Navigator.pop(context), -// ), -// ], -// ); -// } -// } +/// Widget that displays a text file in a dialog. +class TextDisplay extends StatelessWidget { + /// Default Constructor. + const TextDisplay({ + super.key, + required this.filename, + required this.fileContents, + }); + + /// The name of the file. + final String filename; + + /// The contents of the file. + final String fileContents; + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(filename), + content: Scrollbar( + child: SingleChildScrollView(child: Text(fileContents)), + ), + actions: [ + TextButton( + child: const Text('Close'), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } +} diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 3f486beb1278..4d99fc220b48 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -15,11 +15,11 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ -# file_selector: -# git: -# url: https://github.com/bparrishMines/packages -# ref: new_file_selector -# path: packages/file_selector/file_selector + file_selector: + git: + url: https://github.com/bparrishMines/packages + ref: new_file_selector + path: packages/file_selector/file_selector flutter: sdk: flutter mime: ^2.0.0 @@ -35,14 +35,14 @@ flutter: assets: - assets/hello.txt -#dependency_overrides: -# # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because -# # the updated file_selector branch depends on cross_file_darwin from git and this overrides its -# # dependency. -# cross_file_darwin: -# # When depending on this package from a real application you should use: -# # cross_file_darwin: ^x.y.z -# # See https://dart.dev/tools/pub/dependencies#version-constraints -# # The example app is bundled with the plugin so we use a path dependency on -# # the parent directory to use the current plugin's version. -# path: ../ \ No newline at end of file +dependency_overrides: + # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because + # the updated file_selector branch depends on cross_file_darwin from git and this overrides its + # dependency. + cross_file_darwin: + # When depending on this package from a real application you should use: + # cross_file_darwin: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ \ No newline at end of file From 32c511afec4a691c3de02122938b87329541f255 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 12:14:33 -0400 Subject: [PATCH 265/398] remove api and use ffi --- .../lib/src/cross_file_darwin_apis.g.dart | 274 +++++++++--------- ...darwin_scoped_storage_cross_directory.dart | 45 +-- .../src/darwin_scoped_storage_cross_file.dart | 38 +-- .../lib/src/ffi_bindings.g.dart | 22 +- .../cross_file_darwin/tool/ffigen.dart | 1 + 5 files changed, 192 insertions(+), 188 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 771a38c41383..8b80166fe413 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -1,137 +1,137 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.3.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: unused_import, unused_shown_name -// ignore_for_file: type=lint - -import 'dart:async'; -import 'dart:typed_data' show Float64List, Int32List, Int64List; - -import 'package:flutter/services.dart'; -import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; - -Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, -}) { - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } - return replyList.firstOrNull; -} - - - -class _PigeonCodec extends StandardMessageCodec { - const _PigeonCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is int) { - buffer.putUint8(4); - buffer.putInt64(value); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - default: - return super.readValueOfType(type, buffer); - } - } -} - -/// Api for getting access to file information. -class CrossFileDarwinApi { - /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is - /// available for dependency injection. If it is left null, the default - /// BinaryMessenger will be used which routes to the host platform. - CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) - : pigeonVar_binaryMessenger = binaryMessenger, - pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; - final BinaryMessenger? pigeonVar_binaryMessenger; - - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - final String pigeonVar_messageChannelSuffix; - - /// In an app that has adopted App Sandbox, makes the resource pointed to by a - /// security-scoped URL available to the app. - Future startAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; - return pigeonVar_replyValue! as bool; - } - - /// In an app that adopts App Sandbox, revokes access to the resource pointed - /// to by a security-scoped URL. - Future stopAccessingSecurityScopedResource(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ) - ; - } - - /// Whether the native FileManager is able to read a specified file. - Future isReadableFile(String url) async { - final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ) - ; - return pigeonVar_replyValue! as bool; - } -} +// // Copyright 2013 The Flutter Authors +// // Use of this source code is governed by a BSD-style license that can be +// // found in the LICENSE file. +// // Autogenerated from Pigeon (v26.3.4), do not edit directly. +// // See also: https://pub.dev/packages/pigeon +// // ignore_for_file: unused_import, unused_shown_name +// // ignore_for_file: type=lint +// +// import 'dart:async'; +// import 'dart:typed_data' show Float64List, Int32List, Int64List; +// +// import 'package:flutter/services.dart'; +// import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; +// +// Object? _extractReplyValueOrThrow( +// List? replyList, +// String channelName, { +// required bool isNullValid, +// }) { +// if (replyList == null) { +// throw PlatformException( +// code: 'channel-error', +// message: 'Unable to establish connection on channel: "$channelName".', +// ); +// } else if (replyList.length > 1) { +// throw PlatformException( +// code: replyList[0]! as String, +// message: replyList[1] as String?, +// details: replyList[2], +// ); +// } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { +// throw PlatformException( +// code: 'null-error', +// message: 'Host platform returned null value for non-null return value.', +// ); +// } +// return replyList.firstOrNull; +// } +// +// +// +// class _PigeonCodec extends StandardMessageCodec { +// const _PigeonCodec(); +// @override +// void writeValue(WriteBuffer buffer, Object? value) { +// if (value is int) { +// buffer.putUint8(4); +// buffer.putInt64(value); +// } else { +// super.writeValue(buffer, value); +// } +// } +// +// @override +// Object? readValueOfType(int type, ReadBuffer buffer) { +// switch (type) { +// default: +// return super.readValueOfType(type, buffer); +// } +// } +// } +// +// /// Api for getting access to file information. +// class CrossFileDarwinApi { +// /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is +// /// available for dependency injection. If it is left null, the default +// /// BinaryMessenger will be used which routes to the host platform. +// CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) +// : pigeonVar_binaryMessenger = binaryMessenger, +// pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; +// final BinaryMessenger? pigeonVar_binaryMessenger; +// +// static const MessageCodec pigeonChannelCodec = _PigeonCodec(); +// +// final String pigeonVar_messageChannelSuffix; +// +// /// In an app that has adopted App Sandbox, makes the resource pointed to by a +// /// security-scoped URL available to the app. +// Future startAccessingSecurityScopedResource(String url) async { +// final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; +// final pigeonVar_channel = BasicMessageChannel( +// pigeonVar_channelName, +// pigeonChannelCodec, +// binaryMessenger: pigeonVar_binaryMessenger, +// ); +// final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); +// final pigeonVar_replyList = await pigeonVar_sendFuture as List?; +// +// final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( +// pigeonVar_replyList, +// pigeonVar_channelName, +// isNullValid: false, +// ) +// ; +// return pigeonVar_replyValue! as bool; +// } +// +// /// In an app that adopts App Sandbox, revokes access to the resource pointed +// /// to by a security-scoped URL. +// Future stopAccessingSecurityScopedResource(String url) async { +// final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; +// final pigeonVar_channel = BasicMessageChannel( +// pigeonVar_channelName, +// pigeonChannelCodec, +// binaryMessenger: pigeonVar_binaryMessenger, +// ); +// final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); +// final pigeonVar_replyList = await pigeonVar_sendFuture as List?; +// +// _extractReplyValueOrThrow( +// pigeonVar_replyList, +// pigeonVar_channelName, +// isNullValid: true, +// ) +// ; +// } +// +// /// Whether the native FileManager is able to read a specified file. +// Future isReadableFile(String url) async { +// final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; +// final pigeonVar_channel = BasicMessageChannel( +// pigeonVar_channelName, +// pigeonChannelCodec, +// binaryMessenger: pigeonVar_binaryMessenger, +// ); +// final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); +// final pigeonVar_replyList = await pigeonVar_sendFuture as List?; +// +// final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( +// pigeonVar_replyList, +// pigeonVar_channelName, +// isNullValid: false, +// ) +// ; +// return pigeonVar_replyValue! as bool; +// } +// } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 744cf9c37a64..5d5d13ac1264 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -7,9 +7,11 @@ import 'dart:io'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; +import 'package:objective_c/objective_c.dart'; import 'cross_file_darwin_apis.g.dart'; import 'darwin_scoped_storage_cross_file.dart'; +import 'ffi_bindings.g.dart'; import 'security_scoped_resource.dart'; /// Implementation of [PlatformScopedStorageXDirectoryCreationParams] for iOS @@ -24,11 +26,7 @@ sealed class DarwinScopedStorageXDirectoryCreationParams /// scoped uri. factory DarwinScopedStorageXDirectoryCreationParams.securityScoped({ required String uri, - @visibleForTesting CrossFileDarwinApi? api, - }) => SecurityScopedDarwinScopedStorageXDirectoryCreationParams( - uri: uri, - api: api, - ); + }) => SecurityScopedDarwinScopedStorageXDirectoryCreationParams(uri: uri); } /// Creation parameters for [SecurityScopedDarwinScopedStorageXDirectory]. @@ -36,14 +34,9 @@ sealed class DarwinScopedStorageXDirectoryCreationParams base class SecurityScopedDarwinScopedStorageXDirectoryCreationParams extends DarwinScopedStorageXDirectoryCreationParams { /// Constructs a [SecurityScopedDarwinScopedStorageXDirectoryCreationParams]. - SecurityScopedDarwinScopedStorageXDirectoryCreationParams({ + const SecurityScopedDarwinScopedStorageXDirectoryCreationParams({ required super.uri, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(); - - /// The API used to call to native code to interact with files. - @visibleForTesting - final CrossFileDarwinApi api; + }); } /// Base implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. @@ -69,10 +62,13 @@ base class SecurityScopedDarwinScopedStorageXDirectory _finalizer.attach(this, params.uri); } - static final Finalizer _finalizer = Finalizer((String url) { + static final Finalizer _finalizer = Finalizer((String uri) { // Check that this is not called during a unit test. if (Platform.environment['FLUTTER_TEST'] != 'true') { - CrossFileDarwinApi().stopAccessingSecurityScopedResource(url); + final NSURL? url = NSURL.URLWithString(NSString(uri)); + if (url != null) { + url.stopAccessingSecurityScopedResource(); + } } }); @@ -114,18 +110,27 @@ base class SecurityScopedDarwinScopedStorageXDirectory } @override - Future canRead() { - return params.api.isReadableFile(params.uri); + Future canRead() async { + return NSFileManager.getDefaultManager().isReadableFileAtPath( + NSString(Uri.file(params.uri).path), + ); } @override - Future startAccessingSecurityScopedResource() { - return params.api.startAccessingSecurityScopedResource(params.uri); + Future startAccessingSecurityScopedResource() async { + final NSURL? url = NSURL.URLWithString(NSString(params.uri)); + if (url == null) { + return false; + } + return url.startAccessingSecurityScopedResource(); } @override - Future stopAccessingSecurityScopedResource() { - return params.api.stopAccessingSecurityScopedResource(params.uri); + Future stopAccessingSecurityScopedResource() async { + final NSURL? url = NSURL.URLWithString(NSString(params.uri)); + if (url != null) { + url.stopAccessingSecurityScopedResource(); + } } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 5c9cf04e4adb..b96643b05f93 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -29,18 +29,15 @@ sealed class DarwinScopedStorageXFileCreationParams /// scoped uri. factory DarwinScopedStorageXFileCreationParams.securityScoped({ required String uri, - @visibleForTesting CrossFileDarwinApi? api, }) => - SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri, api: api); + SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri); /// Constructs a [DarwinScopedStorageXFileCreationParams] with an asset /// identifier from the Photos Library. factory DarwinScopedStorageXFileCreationParams.photoKit({ required String localIdentifier, - @visibleForTesting CrossFileDarwinApi? api, }) => PhotoKitDarwinScopedStorageXFileCreationParams( localIdentifier: localIdentifier, - api: api, ); } @@ -49,14 +46,9 @@ sealed class DarwinScopedStorageXFileCreationParams base class SecurityScopedDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { /// Constructs a [SecurityScopedDarwinScopedStorageXFileCreationParams]. - SecurityScopedDarwinScopedStorageXFileCreationParams({ + const SecurityScopedDarwinScopedStorageXFileCreationParams({ required super.uri, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(); - - /// The API used to call to native code to interact with files. - @visibleForTesting - final CrossFileDarwinApi api; + }); } /// Creation parameters for [PhotoKitDarwinScopedStorageXFile]. @@ -66,13 +58,7 @@ base class PhotoKitDarwinScopedStorageXFileCreationParams /// Constructs a [PhotoKitDarwinScopedStorageXFileCreationParams]. PhotoKitDarwinScopedStorageXFileCreationParams({ required String localIdentifier, - @visibleForTesting CrossFileDarwinApi? api, - }) : api = api ?? CrossFileDarwinApi(), - super(uri: localIdentifier); - - /// The API used to call to native code to interact with files. - @visibleForTesting - final CrossFileDarwinApi api; + }) : super(uri: localIdentifier); } /// Base implementation of [PlatformScopedStorageXFile] for iOS and macOS. @@ -104,10 +90,13 @@ base class SecurityScopedDarwinScopedStorageXFile _finalizer.attach(this, params.uri); } - static final Finalizer _finalizer = Finalizer((String url) { + static final Finalizer _finalizer = Finalizer((String uri) { // Check that this is not called during a unit test. if (Platform.environment['FLUTTER_TEST'] != 'true') { - CrossFileDarwinApi().stopAccessingSecurityScopedResource(url); + final NSURL? url = NSURL.URLWithString(NSString(uri)); + if (url != null) { + url.stopAccessingSecurityScopedResource(); + } } }); @@ -154,8 +143,10 @@ base class SecurityScopedDarwinScopedStorageXFile _file.readAsString(encoding: encoding); @override - Future canRead() { - return params.api.isReadableFile(params.uri); + Future canRead() async { + return NSFileManager.getDefaultManager().isReadableFileAtPath( + NSString(Uri.file(params.uri).path), + ); } @override @@ -171,7 +162,6 @@ base class SecurityScopedDarwinScopedStorageXFile return false; } return url.startAccessingSecurityScopedResource(); - //return params.api.startAccessingSecurityScopedResource(params.uri); } @override @@ -180,8 +170,6 @@ base class SecurityScopedDarwinScopedStorageXFile if (url != null) { url.stopAccessingSecurityScopedResource(); } - //return url.stopAccessingSecurityScopedResource(); - //return params.api.stopAccessingSecurityScopedResource(params.uri); } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 94f9cab08770..036193154fbe 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -25,12 +25,7 @@ final _objc_msgSend_19nvye5 = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_isReadableFileAtPath_ = objc.registerName( - "isReadableFileAtPath:", -); -late final _sel_homeDirectoryForCurrentUser = objc.registerName( - "homeDirectoryForCurrentUser", -); +late final _sel_defaultManager = objc.registerName("defaultManager"); final _objc_msgSend_151sglz = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -46,6 +41,12 @@ final _objc_msgSend_151sglz = objc.msgSendPointer ffi.Pointer, ) >(); +late final _sel_isReadableFileAtPath_ = objc.registerName( + "isReadableFileAtPath:", +); +late final _sel_homeDirectoryForCurrentUser = objc.registerName( + "homeDirectoryForCurrentUser", +); late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); late final _sel_homeDirectoryForUser_ = objc.registerName( "homeDirectoryForUser:", @@ -139,6 +140,15 @@ extension type NSFileManager._(objc.ObjCObject object$) _sel_isKindOfClass_, _class_NSFileManager, ); + + /// defaultManager + static NSFileManager getDefaultManager() { + final $ret = _objc_msgSend_151sglz( + _class_NSFileManager, + _sel_defaultManager, + ); + return NSFileManager.fromPointer($ret, retain: true, release: true); + } } extension NSFileManager$Methods on NSFileManager { diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 7d24a7fbb07b..8b2aec571367 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -58,6 +58,7 @@ void main() { final signature = member; return switch (interfaceName) { 'NSFileManager' => { + 'defaultManager', 'isReadableFileAtPath:', }.contains(signature), _ => false, From dbee6301723b255ef888657f76927ad2e77ee3a0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 12:27:42 -0400 Subject: [PATCH 266/398] add phasset --- .../lib/src/ffi_bindings.g.dart | 78 +++++++++++++++++++ .../cross_file_darwin/tool/ffigen.dart | 10 +-- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 036193154fbe..566a103ee83c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -161,3 +161,81 @@ extension NSFileManager$Methods on NSFileManager { ); } } + +late final _class_PHObject = objc.getClass("PHObject"); + +/// PHObject +extension type PHObject._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHObject] that points to the same underlying object as [other]. + PHObject.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHObject', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHObject] that wraps the given raw object pointer. + PHObject.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHObject', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHObject]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHObject, + ); +} + +extension PHObject$Methods on PHObject {} + +late final _class_PHAsset = objc.getClass("PHAsset"); + +/// PHAsset +extension type PHAsset._(objc.ObjCObject object$) + implements objc.ObjCObject, PHObject { + /// Constructs a [PHAsset] that points to the same underlying object as [other]. + PHAsset.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAsset', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHAsset] that wraps the given raw object pointer. + PHAsset.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAsset', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHAsset]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHAsset, + ); +} + +extension PHAsset$Methods on PHAsset {} diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 8b2aec571367..3f1eb2ce8b69 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -11,10 +11,10 @@ void main() { FfiGenerator( output: Output( dartFile: packageRoot.resolve('lib/src/ffi_bindings.g.dart'), - // style: const DynamicLibraryBindings( - // wrapperName: 'FoundationFFI', - // wrapperDocComment: 'Bindings for Photos Library.', - // ), + style: const DynamicLibraryBindings( + wrapperName: 'FoundationFFI', + wrapperDocComment: 'Bindings for Foundation and Photos Library.', + ), ), headers: Headers( entryPoints: [ @@ -46,7 +46,7 @@ void main() { include: (Declaration declaration) { return { 'NSFileManager', - // 'PHAsset', + 'PHAsset', // 'PHAssetResource', // 'PHAssetResourceManager', // 'PHFetchResult', From 9eae34ccd5a3031c149e2244bb4bf98ae27e26c2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:34:39 -0400 Subject: [PATCH 267/398] add most api --- .../lib/src/cross_file_darwin.dart | 1 + .../lib/src/ffi_bindings.g.dart | 925 +++++++++++++++++- .../lib/src/ffi_bindings.g.dart.m | 78 ++ .../cross_file_darwin/tool/ffigen.dart | 40 +- 4 files changed, 1034 insertions(+), 10 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index 53b21ab67924..e3c62fb44bd0 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -7,6 +7,7 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'darwin_scoped_storage_cross_directory.dart'; import 'darwin_scoped_storage_cross_file.dart'; +import 'ffi_bindings.g.dart'; /// Implementation of [CrossFilePlatform] for iOS and macOS. base class CrossFileDarwin extends CrossFileIO { diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 566a103ee83c..a1d91e927c23 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -6,6 +6,26 @@ import 'dart:ffi' as ffi; import 'package:objective_c/objective_c.dart' as objc; import 'package:ffi/ffi.dart' as pkg_ffi; +@ffi.Native< + ffi.Pointer Function(ffi.Pointer) +>(isLeaf: true) +external ffi.Pointer +_FoundationFFI_wrapListenerBlock_10c3wkj(ffi.Pointer block); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) +>(isLeaf: true) +external ffi.Pointer +_FoundationFFI_wrapBlockingBlock_10c3wkj( + ffi.Pointer block, + ffi.Pointer listnerBlock, + ffi.Pointer context, +); + late final _class_NSFileManager = objc.getClass("NSFileManager"); late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:"); final _objc_msgSend_19nvye5 = objc.msgSendPointer @@ -201,7 +221,133 @@ extension type PHObject._(objc.ObjCObject object$) extension PHObject$Methods on PHObject {} +late final _class_PHFetchResult = objc.getClass("PHFetchResult"); +late final _sel_firstObject = objc.registerName("firstObject"); + +/// PHFetchResult +extension type PHFetchResult._(objc.ObjCObject object$) + implements + objc.ObjCObject, + objc.NSObject, + objc.NSCopying, + objc.NSFastEnumeration { + /// Constructs a [PHFetchResult] that points to the same underlying object as [other]. + PHFetchResult.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHFetchResult', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHFetchResult] that wraps the given raw object pointer. + PHFetchResult.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHFetchResult', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHFetchResult]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHFetchResult, + ); +} + +extension PHFetchResult$Methods on PHFetchResult { + /// firstObject + objc.ObjCObject? get firstObject { + objc.checkOsVersionInternal( + 'PHFetchResult.firstObject', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_firstObject); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } +} + +enum CGImagePropertyOrientation { + kCGImagePropertyOrientationUp(1), + kCGImagePropertyOrientationUpMirrored(2), + kCGImagePropertyOrientationDown(3), + kCGImagePropertyOrientationDownMirrored(4), + kCGImagePropertyOrientationLeftMirrored(5), + kCGImagePropertyOrientationRight(6), + kCGImagePropertyOrientationRightMirrored(7), + kCGImagePropertyOrientationLeft(8); + + final int value; + const CGImagePropertyOrientation(this.value); + + static CGImagePropertyOrientation fromValue(int value) => switch (value) { + 1 => kCGImagePropertyOrientationUp, + 2 => kCGImagePropertyOrientationUpMirrored, + 3 => kCGImagePropertyOrientationDown, + 4 => kCGImagePropertyOrientationDownMirrored, + 5 => kCGImagePropertyOrientationLeftMirrored, + 6 => kCGImagePropertyOrientationRight, + 7 => kCGImagePropertyOrientationRightMirrored, + 8 => kCGImagePropertyOrientationLeft, + _ => throw ArgumentError( + 'Unknown value for CGImagePropertyOrientation: $value', + ), + }; +} + late final _class_PHAsset = objc.getClass("PHAsset"); +late final _sel_modificationDate = objc.registerName("modificationDate"); + +/// WARNING: PHFetchOptions is a stub. To generate bindings for this class, include +/// PHFetchOptions in your config's objc-interfaces list. +/// +/// PHFetchOptions +extension type PHFetchOptions._(objc.ObjCObject object$) + implements objc.ObjCObject { + /// Constructs a [PHFetchOptions] that points to the same underlying object as [other]. + PHFetchOptions.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [PHFetchOptions] that wraps the given raw object pointer. + PHFetchOptions.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +late final _sel_fetchAssetsWithLocalIdentifiers_options_ = objc.registerName( + "fetchAssetsWithLocalIdentifiers:options:", +); +final _objc_msgSend_15qeuct = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); /// PHAsset extension type PHAsset._(objc.ObjCObject object$) @@ -236,6 +382,783 @@ extension type PHAsset._(objc.ObjCObject object$) _sel_isKindOfClass_, _class_PHAsset, ); + + /// fetchAssetsWithLocalIdentifiers:options: + static PHFetchResult fetchAssetsWithLocalIdentifiers( + objc.NSArray identifiers, { + PHFetchOptions? options, + }) { + objc.checkOsVersionInternal( + 'PHAsset.fetchAssetsWithLocalIdentifiers:options:', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _class_PHAsset, + _sel_fetchAssetsWithLocalIdentifiers_options_, + identifiers.ref.pointer, + options?.ref.pointer ?? ffi.nullptr, + ); + return PHFetchResult.fromPointer($ret, retain: true, release: true); + } +} + +extension PHAsset$Methods on PHAsset { + /// The date and time of the last modification to this asset or one of its properties + objc.NSDate? get modificationDate { + objc.checkOsVersionInternal( + 'PHAsset.modificationDate', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_modificationDate, + ); + return $ret.address == 0 + ? null + : objc.NSDate.fromPointer($ret, retain: true, release: true); + } +} + +late final _class_PHAssetResource = objc.getClass("PHAssetResource"); +late final _sel_originalFilename = objc.registerName("originalFilename"); +late final _sel_assetResourcesForAsset_ = objc.registerName( + "assetResourcesForAsset:", +); + +/// PHAssetResource +extension type PHAssetResource._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHAssetResource] that points to the same underlying object as [other]. + PHAssetResource.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAssetResource', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHAssetResource] that wraps the given raw object pointer. + PHAssetResource.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAssetResource', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHAssetResource]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHAssetResource, + ); + + /// assetResourcesForAsset: + static objc.NSArray assetResourcesForAsset(PHAsset asset) { + objc.checkOsVersionInternal( + 'PHAssetResource.assetResourcesForAsset:', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _class_PHAssetResource, + _sel_assetResourcesForAsset_, + asset.ref.pointer, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } +} + +extension PHAssetResource$Methods on PHAssetResource { + /// originalFilename + objc.NSString get originalFilename { + objc.checkOsVersionInternal( + 'PHAssetResource.originalFilename', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_originalFilename, + ); + return objc.NSString.fromPointer($ret, retain: true, release: true); + } } -extension PHAsset$Methods on PHAsset {} +late final _class_PHImageRequestOptions = objc.getClass( + "PHImageRequestOptions", +); +late final _sel_isNetworkAccessAllowed = objc.registerName( + "isNetworkAccessAllowed", +); +final _objc_msgSend_91o635 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// PHImageRequestOptions +extension type PHImageRequestOptions._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHImageRequestOptions] that points to the same underlying object as [other]. + PHImageRequestOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHImageRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHImageRequestOptions] that wraps the given raw object pointer. + PHImageRequestOptions.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHImageRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHImageRequestOptions]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHImageRequestOptions, + ); +} + +extension PHImageRequestOptions$Methods on PHImageRequestOptions { + /// isNetworkAccessAllowed + bool get isNetworkAccessAllowed { + objc.checkOsVersionInternal( + 'PHImageRequestOptions.isNetworkAccessAllowed', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + return _objc_msgSend_91o635( + object$.ref.pointer, + _sel_isNetworkAccessAllowed, + ); + } +} + +late final _class_PHImageManager = objc.getClass("PHImageManager"); + +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + fromPointer( + ffi.Pointer pointer, { + bool retain = false, + bool release = false, + }) => + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >(pointer, retain: retain, release: release); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + > + ptr, + ) => + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + fromFunction( + void Function( + objc.NSData?, + objc.NSString?, + CGImagePropertyOrientation, + objc.NSDictionary?, + ) + fn, { + bool keepIsolateAlive = true, + }) => + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >( + objc.newClosureBlock( + _closureCallable, + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: true, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: true, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer( + arg3, + retain: true, + release: true, + ), + ), + keepIsolateAlive, + ), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This is based on FFI's NativeCallable.listener, and has the same + /// capabilities and limitations. This block can be invoked from any thread, + /// but only supports void functions, and is not run synchronously. See + /// NativeCallable.listener for more details. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + listener( + void Function( + objc.NSData?, + objc.NSString?, + CGImagePropertyOrientation, + objc.NSDictionary?, + ) + fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _listenerCallable.nativeFunction.cast(), + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: false, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + ), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapListenerBlock_10c3wkj(raw); + objc.objectRelease(raw.cast()); + return objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >(wrapper, retain: false, release: true); + } + + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + blocking( + void Function( + objc.NSData?, + objc.NSString?, + CGImagePropertyOrientation, + objc.NSDictionary?, + ) + fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _blockingCallable.nativeFunction.cast(), + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: false, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + ), + keepIsolateAlive, + ); + final rawListener = objc.newClosureBlock( + _blockingListenerCallable.nativeFunction.cast(), + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: false, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + ), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapBlockingBlock_10c3wkj( + raw, + rawListener, + objc.objCContext, + ); + objc.objectRelease(raw.cast()); + objc.objectRelease(rawListener.cast()); + return objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >(wrapper, retain: false, release: true); + } + + static void _listenerTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) { + (objc.getBlockClosure(block) + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); + objc.objectRelease(block.cast()); + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + > + _listenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >.listener(_listenerTrampoline) + ..keepIsolateAlive = false; + static void _blockingTrampoline( + ffi.Pointer block, + ffi.Pointer waiter, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) { + try { + (objc.getBlockClosure(block) + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); + } catch (e) { + } finally { + objc.signalWaiter(waiter); + objc.objectRelease(block.cast()); + } + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + > + _blockingCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >.isolateLocal(_blockingTrampoline) + ..keepIsolateAlive = false; + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + > + _blockingListenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >.listener(_blockingTrampoline) + ..keepIsolateAlive = false; + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => block.ref.target + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >()(arg0, arg1, arg2, arg3); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => + (objc.getBlockClosure(block) + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >(_closureTrampoline) + .cast(); +} + +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary$CallExtension + on + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > { + void call( + objc.NSData? arg0, + objc.NSString? arg1, + CGImagePropertyOrientation arg2, + objc.NSDictionary? arg3, + ) => + ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >()( + ref.pointer, + arg0?.ref.pointer ?? ffi.nullptr, + arg1?.ref.pointer ?? ffi.nullptr, + arg2.value, + arg3?.ref.pointer ?? ffi.nullptr, + ); +} + +late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = + objc.registerName( + "requestImageDataAndOrientationForAsset:options:resultHandler:", + ); +final _objc_msgSend_1urj8nv = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// PHImageManager +extension type PHImageManager._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHImageManager] that points to the same underlying object as [other]. + PHImageManager.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHImageManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHImageManager] that wraps the given raw object pointer. + PHImageManager.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHImageManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHImageManager]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHImageManager, + ); + + /// defaultManager + static PHImageManager defaultManager() { + objc.checkOsVersionInternal( + 'PHImageManager.defaultManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_151sglz( + _class_PHImageManager, + _sel_defaultManager, + ); + return PHImageManager.fromPointer($ret, retain: true, release: true); + } +} + +extension PHImageManager$Methods on PHImageManager { + /// @abstract Request largest represented image as data bytes and EXIF orientation for the specified asset. + /// @param asset The asset whose image data is to be loaded. + /// @param options Options specifying how Photos should handle the request, format the requested image, and notify your app of progress or errors. + /// If PHImageRequestOptionsVersionCurrent is requested and the asset has adjustments then the largest rendered image data is returned. In all other cases then the original image data is returned. + /// @param resultHandler A block that is called exactly once either synchronously on the current thread or asynchronously on the main thread depending on the synchronous option specified in the PHImageRequestOptions options parameter (deliveryMode is ignored). Orientation is an EXIF orientation as an CGImagePropertyOrientation. For iOS or tvOS, convert this to an UIImageOrientation. + int requestImageDataAndOrientationForAsset( + PHAsset asset, { + PHImageRequestOptions? options, + required objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + resultHandler, + }) { + objc.checkOsVersionInternal( + 'PHImageManager.requestImageDataAndOrientationForAsset:options:resultHandler:', + iOS: (false, (13, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + return _objc_msgSend_1urj8nv( + object$.ref.pointer, + _sel_requestImageDataAndOrientationForAsset_options_resultHandler_, + asset.ref.pointer, + options?.ref.pointer ?? ffi.nullptr, + resultHandler.ref.pointer, + ); + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m new file mode 100644 index 000000000000..6eef5f92fbad --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m @@ -0,0 +1,78 @@ +#include +#import +#import +#import +#import +#import + +#if !__has_feature(objc_arc) +#error "This file must be compiled with ARC enabled" +#endif + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + +typedef struct { + int64_t version; + void* (*newWaiter)(void); + void (*awaitWaiter)(void*); + void* (*currentIsolate)(void); + void (*enterIsolate)(void*); + void (*exitIsolate)(void); + int64_t (*getMainPortId)(void); + bool (*getCurrentThreadOwnsIsolate)(int64_t); +} DOBJC_Context; + +id objc_retainBlock(id); + +#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ + assert(ctx->version >= 1); \ + void* targetIsolate = ctx->currentIsolate(); \ + int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ + return BLOCK_SIG { \ + void* currentIsolate = ctx->currentIsolate(); \ + bool mayEnterIsolate = \ + currentIsolate == NULL && \ + ctx->getCurrentThreadOwnsIsolate != NULL && \ + ctx->getCurrentThreadOwnsIsolate(targetPort); \ + if (currentIsolate == targetIsolate || mayEnterIsolate) { \ + if (mayEnterIsolate) { \ + ctx->enterIsolate(targetIsolate); \ + } \ + INVOKE_DIRECT; \ + if (mayEnterIsolate) { \ + ctx->exitIsolate(); \ + } \ + } else { \ + void* waiter = ctx->newWaiter(); \ + INVOKE_LISTENER; \ + ctx->awaitWaiter(waiter); \ + } \ + }; + + +typedef void (^_ListenerTrampoline)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline _FoundationFFI_wrapListenerBlock_10c3wkj(_ListenerTrampoline block) NS_RETURNS_RETAINED { + return ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { + objc_retainBlock(block); + block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + }; +} + +typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline _FoundationFFI_wrapBlockingBlock_10c3wkj( + _BlockingTrampoline block, _BlockingTrampoline listenerBlock, + DOBJC_Context* ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + }, { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + }); +} +#undef BLOCKING_BLOCK_IMPL + +#pragma clang diagnostic pop diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 3f1eb2ce8b69..d93be6618e5e 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -27,19 +27,20 @@ void main() { Uri.file( '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAsset.h', ), - // Uri.file( - // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResource.h', - // ), + Uri.file( + '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResource.h', + ), // Uri.file( // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResourceManager.h', // ), // Uri.file( // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHFetchResult.h', // ), - // Uri.file( - // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHImageManager.h', - // ), + Uri.file( + '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHImageManager.h', + ), ], + compilerOptions: ['-include stdint.h'], ), objectiveC: ObjectiveC( interfaces: Interfaces( @@ -47,13 +48,18 @@ void main() { return { 'NSFileManager', 'PHAsset', - // 'PHAssetResource', + 'PHAssetResource', // 'PHAssetResourceManager', - // 'PHFetchResult', - // 'PHImageManager', + 'PHFetchResult', + 'PHImageManager', + 'PHImageRequestOptions', }.contains(declaration.originalName); }, includeMember: (Declaration declaration, String member) { + if (declaration.originalName == 'PHAssetResource' && + member.contains('assetResources')) { + print('APPLE: $member'); + } final String interfaceName = declaration.originalName; final signature = member; return switch (interfaceName) { @@ -61,6 +67,22 @@ void main() { 'defaultManager', 'isReadableFileAtPath:', }.contains(signature), + 'PHAsset' => { + 'fetchAssetsWithLocalIdentifiers:options:', + 'modificationDate', + }.contains(signature), + 'PHAssetResource' => { + 'assetResourcesForAsset:', + 'originalFilename', + }.contains(signature), + 'PHFetchResult' => {'firstObject'}.contains(signature), + 'PHImageManager' => { + 'defaultManager', + 'requestImageDataAndOrientationForAsset:options:resultHandler:', + }.contains(signature), + 'PHImageRequestOptions' => { + 'isNetworkAccessAllowed', + }.contains(signature), _ => false, }; }, From 04621c32e3b4cb8ffe266efd90a8822a86304570 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:45:54 -0400 Subject: [PATCH 268/398] finish adding bindingS --- .../lib/src/ffi_bindings.g.dart | 2081 +++++++++++++---- .../lib/src/ffi_bindings.g.dart.m | 60 +- .../cross_file_darwin/tool/ffigen.dart | 40 +- 3 files changed, 1684 insertions(+), 497 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index a1d91e927c23..76347bdc2678 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -6,6 +6,26 @@ import 'dart:ffi' as ffi; import 'package:objective_c/objective_c.dart' as objc; import 'package:ffi/ffi.dart' as pkg_ffi; +@ffi.Native< + ffi.Pointer Function(ffi.Pointer) +>(isLeaf: true) +external ffi.Pointer +_FoundationFFI_wrapListenerBlock_pfv6jd(ffi.Pointer block); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) +>(isLeaf: true) +external ffi.Pointer +_FoundationFFI_wrapBlockingBlock_pfv6jd( + ffi.Pointer block, + ffi.Pointer listnerBlock, + ffi.Pointer context, +); + @ffi.Native< ffi.Pointer Function(ffi.Pointer) >(isLeaf: true) @@ -26,6 +46,26 @@ _FoundationFFI_wrapBlockingBlock_10c3wkj( ffi.Pointer context, ); +@ffi.Native< + ffi.Pointer Function(ffi.Pointer) +>(isLeaf: true) +external ffi.Pointer +_FoundationFFI_wrapListenerBlock_xtuoz7(ffi.Pointer block); + +@ffi.Native< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) +>(isLeaf: true) +external ffi.Pointer +_FoundationFFI_wrapBlockingBlock_xtuoz7( + ffi.Pointer block, + ffi.Pointer listnerBlock, + ffi.Pointer context, +); + late final _class_NSFileManager = objc.getClass("NSFileManager"); late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:"); final _objc_msgSend_19nvye5 = objc.msgSendPointer @@ -314,16 +354,28 @@ late final _sel_modificationDate = objc.registerName("modificationDate"); /// /// PHFetchOptions extension type PHFetchOptions._(objc.ObjCObject object$) - implements objc.ObjCObject { + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { /// Constructs a [PHFetchOptions] that points to the same underlying object as [other]. - PHFetchOptions.as(objc.ObjCObject other) : object$ = other {} + PHFetchOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHFetchOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + } /// Constructs a [PHFetchOptions] that wraps the given raw object pointer. PHFetchOptions.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHFetchOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + } } late final _sel_fetchAssetsWithLocalIdentifiers_options_ = objc.registerName( @@ -349,234 +401,70 @@ final _objc_msgSend_15qeuct = objc.msgSendPointer ) >(); -/// PHAsset -extension type PHAsset._(objc.ObjCObject object$) - implements objc.ObjCObject, PHObject { - /// Constructs a [PHAsset] that points to the same underlying object as [other]. - PHAsset.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHAsset', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - assert(isA(object$)); - } - - /// Constructs a [PHAsset] that wraps the given raw object pointer. - PHAsset.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHAsset', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - assert(isA(object$)); - } - - /// Returns whether [obj] is an instance of [PHAsset]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHAsset, - ); - - /// fetchAssetsWithLocalIdentifiers:options: - static PHFetchResult fetchAssetsWithLocalIdentifiers( - objc.NSArray identifiers, { - PHFetchOptions? options, - }) { - objc.checkOsVersionInternal( - 'PHAsset.fetchAssetsWithLocalIdentifiers:options:', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - final $ret = _objc_msgSend_15qeuct( - _class_PHAsset, - _sel_fetchAssetsWithLocalIdentifiers_options_, - identifiers.ref.pointer, - options?.ref.pointer ?? ffi.nullptr, - ); - return PHFetchResult.fromPointer($ret, retain: true, release: true); - } -} - -extension PHAsset$Methods on PHAsset { - /// The date and time of the last modification to this asset or one of its properties - objc.NSDate? get modificationDate { - objc.checkOsVersionInternal( - 'PHAsset.modificationDate', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_modificationDate, - ); - return $ret.address == 0 - ? null - : objc.NSDate.fromPointer($ret, retain: true, release: true); - } -} - -late final _class_PHAssetResource = objc.getClass("PHAssetResource"); -late final _sel_originalFilename = objc.registerName("originalFilename"); -late final _sel_assetResourcesForAsset_ = objc.registerName( - "assetResourcesForAsset:", -); - -/// PHAssetResource -extension type PHAssetResource._(objc.ObjCObject object$) +/// WARNING: PHContentEditingInputRequestOptions is a stub. To generate bindings for this class, include +/// PHContentEditingInputRequestOptions in your config's objc-interfaces list. +/// +/// PHContentEditingInputRequestOptions +extension type PHContentEditingInputRequestOptions._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHAssetResource] that points to the same underlying object as [other]. - PHAssetResource.as(objc.ObjCObject other) : object$ = other { + /// Constructs a [PHContentEditingInputRequestOptions] that points to the same underlying object as [other]. + PHContentEditingInputRequestOptions.as(objc.ObjCObject other) + : object$ = other { objc.checkOsVersionInternal( - 'PHAssetResource', - iOS: (false, (9, 0, 0)), + 'PHContentEditingInputRequestOptions', + iOS: (false, (8, 0, 0)), macOS: (false, (10, 15, 0)), ); - assert(isA(object$)); } - /// Constructs a [PHAssetResource] that wraps the given raw object pointer. - PHAssetResource.fromPointer( + /// Constructs a [PHContentEditingInputRequestOptions] that wraps the given raw object pointer. + PHContentEditingInputRequestOptions.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { objc.checkOsVersionInternal( - 'PHAssetResource', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - assert(isA(object$)); - } - - /// Returns whether [obj] is an instance of [PHAssetResource]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHAssetResource, - ); - - /// assetResourcesForAsset: - static objc.NSArray assetResourcesForAsset(PHAsset asset) { - objc.checkOsVersionInternal( - 'PHAssetResource.assetResourcesForAsset:', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - _class_PHAssetResource, - _sel_assetResourcesForAsset_, - asset.ref.pointer, - ); - return objc.NSArray.fromPointer($ret, retain: true, release: true); - } -} - -extension PHAssetResource$Methods on PHAssetResource { - /// originalFilename - objc.NSString get originalFilename { - objc.checkOsVersionInternal( - 'PHAssetResource.originalFilename', - iOS: (false, (9, 0, 0)), + 'PHContentEditingInputRequestOptions', + iOS: (false, (8, 0, 0)), macOS: (false, (10, 15, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_originalFilename, - ); - return objc.NSString.fromPointer($ret, retain: true, release: true); } } -late final _class_PHImageRequestOptions = objc.getClass( - "PHImageRequestOptions", -); -late final _sel_isNetworkAccessAllowed = objc.registerName( - "isNetworkAccessAllowed", -); -final _objc_msgSend_91o635 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - bool Function( - ffi.Pointer, - ffi.Pointer, - ) - >(); - -/// PHImageRequestOptions -extension type PHImageRequestOptions._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject, objc.NSCopying { - /// Constructs a [PHImageRequestOptions] that points to the same underlying object as [other]. - PHImageRequestOptions.as(objc.ObjCObject other) : object$ = other { +/// WARNING: PHContentEditingInput is a stub. To generate bindings for this class, include +/// PHContentEditingInput in your config's objc-interfaces list. +/// +/// PHContentEditingInput +extension type PHContentEditingInput._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHContentEditingInput] that points to the same underlying object as [other]. + PHContentEditingInput.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( - 'PHImageRequestOptions', + 'PHContentEditingInput', iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), + macOS: (false, (10, 11, 0)), ); - assert(isA(object$)); } - /// Constructs a [PHImageRequestOptions] that wraps the given raw object pointer. - PHImageRequestOptions.fromPointer( + /// Constructs a [PHContentEditingInput] that wraps the given raw object pointer. + PHContentEditingInput.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { objc.checkOsVersionInternal( - 'PHImageRequestOptions', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - assert(isA(object$)); - } - - /// Returns whether [obj] is an instance of [PHImageRequestOptions]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHImageRequestOptions, - ); -} - -extension PHImageRequestOptions$Methods on PHImageRequestOptions { - /// isNetworkAccessAllowed - bool get isNetworkAccessAllowed { - objc.checkOsVersionInternal( - 'PHImageRequestOptions.isNetworkAccessAllowed', + 'PHContentEditingInput', iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - return _objc_msgSend_91o635( - object$.ref.pointer, - _sel_isNetworkAccessAllowed, + macOS: (false, (10, 11, 0)), ); } } -late final _class_PHImageManager = objc.getClass("PHImageManager"); - -/// Construction methods for `objc.ObjCBlock`. -abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary { +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// Returns a block that wraps the given raw block pointer. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) > fromPointer( ffi.Pointer pointer, { @@ -584,12 +472,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio bool release = false, }) => objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) >(pointer, retain: retain, release: release); /// Creates a block from a C function pointer. @@ -598,12 +481,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) > fromFunctionPointer( ffi.Pointer< @@ -611,20 +489,13 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Void Function( ffi.Pointer arg0, ffi.Pointer arg1, - ffi.Uint32 arg2, - ffi.Pointer arg3, ) > > ptr, ) => objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) >( objc.newPointerBlock(_fnPtrCallable, ptr.cast()), retain: false, @@ -640,53 +511,29 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) > fromFunction( - void Function( - objc.NSData?, - objc.NSString?, - CGImagePropertyOrientation, - objc.NSDictionary?, - ) - fn, { + void Function(PHContentEditingInput?, objc.NSDictionary) fn, { bool keepIsolateAlive = true, }) => objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) >( objc.newClosureBlock( _closureCallable, ( ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) => fn( arg0.address == 0 ? null - : objc.NSData.fromPointer(arg0, retain: true, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: true, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer( - arg3, + : PHContentEditingInput.fromPointer( + arg0, retain: true, release: true, ), + objc.NSDictionary.fromPointer(arg1, retain: true, release: true), ), keepIsolateAlive, ), @@ -704,21 +551,10 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) > listener( - void Function( - objc.NSData?, - objc.NSString?, - CGImagePropertyOrientation, - objc.NSDictionary?, - ) - fn, { + void Function(PHContentEditingInput?, objc.NSDictionary) fn, { bool keepIsolateAlive = true, }) { final raw = objc.newClosureBlock( @@ -726,31 +562,22 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ( ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) => fn( arg0.address == 0 ? null - : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: false, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + : PHContentEditingInput.fromPointer( + arg0, + retain: false, + release: true, + ), + objc.NSDictionary.fromPointer(arg1, retain: false, release: true), ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapListenerBlock_10c3wkj(raw); + final wrapper = _FoundationFFI_wrapListenerBlock_pfv6jd(raw); objc.objectRelease(raw.cast()); return objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) >(wrapper, retain: false, release: true); } @@ -765,21 +592,10 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// has shut down, and the block is invoked by native code, it may block /// indefinitely, or have other undefined behavior. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) > blocking( - void Function( - objc.NSData?, - objc.NSString?, - CGImagePropertyOrientation, - objc.NSDictionary?, - ) - fn, { + void Function(PHContentEditingInput?, objc.NSDictionary) fn, { bool keepIsolateAlive = true, }) { final raw = objc.newClosureBlock( @@ -787,19 +603,15 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ( ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) => fn( arg0.address == 0 ? null - : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: false, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + : PHContentEditingInput.fromPointer( + arg0, + retain: false, + release: true, + ), + objc.NSDictionary.fromPointer(arg1, retain: false, release: true), ), keepIsolateAlive, ); @@ -808,23 +620,19 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ( ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) => fn( arg0.address == 0 ? null - : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: false, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + : PHContentEditingInput.fromPointer( + arg0, + retain: false, + release: true, + ), + objc.NSDictionary.fromPointer(arg1, retain: false, release: true), ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapBlockingBlock_10c3wkj( + final wrapper = _FoundationFFI_wrapBlockingBlock_pfv6jd( raw, rawListener, objc.objCContext, @@ -832,12 +640,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio objc.objectRelease(raw.cast()); objc.objectRelease(rawListener.cast()); return objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) >(wrapper, retain: false, release: true); } @@ -845,16 +648,12 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) { (objc.getBlockClosure(block) as void Function( ffi.Pointer, ffi.Pointer, - int, - ffi.Pointer, - ))(arg0, arg1, arg2, arg3); + ))(arg0, arg1); objc.objectRelease(block.cast()); } @@ -863,8 +662,6 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) > _listenerCallable = @@ -873,8 +670,6 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) >.listener(_listenerTrampoline) ..keepIsolateAlive = false; @@ -883,17 +678,13 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer waiter, ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) { try { (objc.getBlockClosure(block) as void Function( ffi.Pointer, ffi.Pointer, - int, - ffi.Pointer, - ))(arg0, arg1, arg2, arg3); + ))(arg0, arg1); } catch (e) { } finally { objc.signalWaiter(waiter); @@ -907,8 +698,6 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) > _blockingCallable = @@ -918,8 +707,6 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) >.isolateLocal(_blockingTrampoline) ..keepIsolateAlive = false; @@ -929,8 +716,6 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) > _blockingListenerCallable = @@ -940,8 +725,6 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) >.listener(_blockingTrampoline) ..keepIsolateAlive = false; @@ -949,16 +732,12 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) => block.ref.target .cast< ffi.NativeFunction< ffi.Void Function( ffi.Pointer arg0, ffi.Pointer arg1, - ffi.Uint32 arg2, - ffi.Pointer arg3, ) > >() @@ -966,18 +745,14 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio void Function( ffi.Pointer, ffi.Pointer, - int, - ffi.Pointer, ) - >()(arg0, arg1, arg2, arg3); + >()(arg0, arg1); static ffi.Pointer _fnPtrCallable = ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) >(_fnPtrTrampoline) .cast(); @@ -985,87 +760,60 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, ) => (objc.getBlockClosure(block) as void Function( ffi.Pointer, ffi.Pointer, - int, - ffi.Pointer, - ))(arg0, arg1, arg2, arg3); + ))(arg0, arg1); static ffi.Pointer _closureCallable = ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Uint32, - ffi.Pointer, ) >(_closureTrampoline) .cast(); } -/// Call operator for `objc.ObjCBlock`. -extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary$CallExtension +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary$CallExtension on objc.ObjCBlock< + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) + > { + void call(PHContentEditingInput? arg0, objc.NSDictionary arg1) => ref + .pointer + .ref + .invoke + .cast< + ffi.NativeFunction< ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, ) - > { - void call( - objc.NSData? arg0, - objc.NSString? arg1, - CGImagePropertyOrientation arg2, - objc.NSDictionary? arg3, - ) => - ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Uint32 arg2, - ffi.Pointer arg3, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >()( - ref.pointer, - arg0?.ref.pointer ?? ffi.nullptr, - arg1?.ref.pointer ?? ffi.nullptr, - arg2.value, - arg3?.ref.pointer ?? ffi.nullptr, - ); + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >()(ref.pointer, arg0?.ref.pointer ?? ffi.nullptr, arg1.ref.pointer); } -late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = - objc.registerName( - "requestImageDataAndOrientationForAsset:options:resultHandler:", - ); -final _objc_msgSend_1urj8nv = objc.msgSendPointer +late final _sel_requestContentEditingInputWithOptions_completionHandler_ = objc + .registerName("requestContentEditingInputWithOptions:completionHandler:"); +final _objc_msgSend_jkkt9d = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.Int32 Function( + ffi.UnsignedLong Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer, ) > @@ -1075,90 +823,1513 @@ final _objc_msgSend_1urj8nv = objc.msgSendPointer ffi.Pointer, ffi.Pointer, ffi.Pointer, - ffi.Pointer, ffi.Pointer, ) >(); +late final _sel_cancelContentEditingInputRequest_ = objc.registerName( + "cancelContentEditingInputRequest:", +); +final _objc_msgSend_1i9r4xy = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ) + >(); -/// PHImageManager -extension type PHImageManager._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHImageManager] that points to the same underlying object as [other]. - PHImageManager.as(objc.ObjCObject other) : object$ = other { +/// PHContentEditingInput +extension PHContentEditingInput$1 on PHAsset { + /// cancelContentEditingInputRequest: + void cancelContentEditingInputRequest(int requestID) { objc.checkOsVersionInternal( - 'PHImageManager', + 'PHAsset.cancelContentEditingInputRequest:', iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), + macOS: (false, (10, 15, 0)), + ); + _objc_msgSend_1i9r4xy( + object$.ref.pointer, + _sel_cancelContentEditingInputRequest_, + requestID, ); - assert(isA(object$)); } - /// Constructs a [PHImageManager] that wraps the given raw object pointer. - PHImageManager.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + /// requestContentEditingInputWithOptions:completionHandler: + int requestContentEditingInputWithOptions( + PHContentEditingInputRequestOptions? options, { + required objc.ObjCBlock< + ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) + > + completionHandler, + }) { objc.checkOsVersionInternal( - 'PHImageManager', + 'PHAsset.requestContentEditingInputWithOptions:completionHandler:', iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), + macOS: (false, (10, 15, 0)), + ); + return _objc_msgSend_jkkt9d( + object$.ref.pointer, + _sel_requestContentEditingInputWithOptions_completionHandler_, + options?.ref.pointer ?? ffi.nullptr, + completionHandler.ref.pointer, ); - assert(isA(object$)); } +} - /// Returns whether [obj] is an instance of [PHImageManager]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, +/// PHAsset +extension type PHAsset._(objc.ObjCObject object$) + implements objc.ObjCObject, PHObject { + /// Constructs a [PHAsset] that points to the same underlying object as [other]. + PHAsset.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAsset', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHAsset] that wraps the given raw object pointer. + PHAsset.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAsset', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHAsset]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHAsset, + ); + + /// fetchAssetsWithLocalIdentifiers:options: + static PHFetchResult fetchAssetsWithLocalIdentifiers( + objc.NSArray identifiers, { + PHFetchOptions? options, + }) { + objc.checkOsVersionInternal( + 'PHAsset.fetchAssetsWithLocalIdentifiers:options:', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _class_PHAsset, + _sel_fetchAssetsWithLocalIdentifiers_options_, + identifiers.ref.pointer, + options?.ref.pointer ?? ffi.nullptr, + ); + return PHFetchResult.fromPointer($ret, retain: true, release: true); + } +} + +extension PHAsset$Methods on PHAsset { + /// modificationDate + objc.NSDate? get modificationDate { + objc.checkOsVersionInternal( + 'PHAsset.modificationDate', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_modificationDate, + ); + return $ret.address == 0 + ? null + : objc.NSDate.fromPointer($ret, retain: true, release: true); + } +} + +late final _class_PHImageRequestOptions = objc.getClass( + "PHImageRequestOptions", +); +late final _sel_isNetworkAccessAllowed = objc.registerName( + "isNetworkAccessAllowed", +); +final _objc_msgSend_91o635 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// PHImageRequestOptions +extension type PHImageRequestOptions._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHImageRequestOptions] that points to the same underlying object as [other]. + PHImageRequestOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHImageRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHImageRequestOptions] that wraps the given raw object pointer. + PHImageRequestOptions.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHImageRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHImageRequestOptions]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHImageRequestOptions, + ); +} + +extension PHImageRequestOptions$Methods on PHImageRequestOptions { + /// isNetworkAccessAllowed + bool get isNetworkAccessAllowed { + objc.checkOsVersionInternal( + 'PHImageRequestOptions.isNetworkAccessAllowed', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + return _objc_msgSend_91o635( + object$.ref.pointer, + _sel_isNetworkAccessAllowed, + ); + } +} + +late final _class_PHImageManager = objc.getClass("PHImageManager"); + +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + fromPointer( + ffi.Pointer pointer, { + bool retain = false, + bool release = false, + }) => + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >(pointer, retain: retain, release: release); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + > + ptr, + ) => + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + fromFunction( + void Function( + objc.NSData?, + objc.NSString?, + CGImagePropertyOrientation, + objc.NSDictionary?, + ) + fn, { + bool keepIsolateAlive = true, + }) => + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >( + objc.newClosureBlock( + _closureCallable, + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: true, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: true, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer( + arg3, + retain: true, + release: true, + ), + ), + keepIsolateAlive, + ), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This is based on FFI's NativeCallable.listener, and has the same + /// capabilities and limitations. This block can be invoked from any thread, + /// but only supports void functions, and is not run synchronously. See + /// NativeCallable.listener for more details. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + listener( + void Function( + objc.NSData?, + objc.NSString?, + CGImagePropertyOrientation, + objc.NSDictionary?, + ) + fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _listenerCallable.nativeFunction.cast(), + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: false, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + ), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapListenerBlock_10c3wkj(raw); + objc.objectRelease(raw.cast()); + return objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >(wrapper, retain: false, release: true); + } + + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + blocking( + void Function( + objc.NSData?, + objc.NSString?, + CGImagePropertyOrientation, + objc.NSDictionary?, + ) + fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _blockingCallable.nativeFunction.cast(), + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: false, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + ), + keepIsolateAlive, + ); + final rawListener = objc.newClosureBlock( + _blockingListenerCallable.nativeFunction.cast(), + ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => fn( + arg0.address == 0 + ? null + : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 + ? null + : objc.NSString.fromPointer(arg1, retain: false, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), + ), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapBlockingBlock_10c3wkj( + raw, + rawListener, + objc.objCContext, + ); + objc.objectRelease(raw.cast()); + objc.objectRelease(rawListener.cast()); + return objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + >(wrapper, retain: false, release: true); + } + + static void _listenerTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) { + (objc.getBlockClosure(block) + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); + objc.objectRelease(block.cast()); + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + > + _listenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >.listener(_listenerTrampoline) + ..keepIsolateAlive = false; + static void _blockingTrampoline( + ffi.Pointer block, + ffi.Pointer waiter, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) { + try { + (objc.getBlockClosure(block) + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); + } catch (e) { + } finally { + objc.signalWaiter(waiter); + objc.objectRelease(block.cast()); + } + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + > + _blockingCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >.isolateLocal(_blockingTrampoline) + ..keepIsolateAlive = false; + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + > + _blockingListenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >.listener(_blockingTrampoline) + ..keepIsolateAlive = false; + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => block.ref.target + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >()(arg0, arg1, arg2, arg3); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) => + (objc.getBlockClosure(block) + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Uint32, + ffi.Pointer, + ) + >(_closureTrampoline) + .cast(); +} + +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary$CallExtension + on + objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > { + void call( + objc.NSData? arg0, + objc.NSString? arg1, + CGImagePropertyOrientation arg2, + objc.NSDictionary? arg3, + ) => + ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >()( + ref.pointer, + arg0?.ref.pointer ?? ffi.nullptr, + arg1?.ref.pointer ?? ffi.nullptr, + arg2.value, + arg3?.ref.pointer ?? ffi.nullptr, + ); +} + +late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = + objc.registerName( + "requestImageDataAndOrientationForAsset:options:resultHandler:", + ); +final _objc_msgSend_1urj8nv = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// PHImageManager +extension type PHImageManager._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHImageManager] that points to the same underlying object as [other]. + PHImageManager.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHImageManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHImageManager] that wraps the given raw object pointer. + PHImageManager.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHImageManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHImageManager]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, _class_PHImageManager, ); /// defaultManager - static PHImageManager defaultManager() { + static PHImageManager defaultManager() { + objc.checkOsVersionInternal( + 'PHImageManager.defaultManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_151sglz( + _class_PHImageManager, + _sel_defaultManager, + ); + return PHImageManager.fromPointer($ret, retain: true, release: true); + } +} + +extension PHImageManager$Methods on PHImageManager { + /// requestImageDataAndOrientationForAsset:options:resultHandler: + int requestImageDataAndOrientationForAsset( + PHAsset asset, { + PHImageRequestOptions? options, + required objc.ObjCBlock< + ffi.Void Function( + objc.NSData?, + objc.NSString?, + ffi.Uint32, + objc.NSDictionary?, + ) + > + resultHandler, + }) { + objc.checkOsVersionInternal( + 'PHImageManager.requestImageDataAndOrientationForAsset:options:resultHandler:', + iOS: (false, (13, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + return _objc_msgSend_1urj8nv( + object$.ref.pointer, + _sel_requestImageDataAndOrientationForAsset_options_resultHandler_, + asset.ref.pointer, + options?.ref.pointer ?? ffi.nullptr, + resultHandler.ref.pointer, + ); + } +} + +/// WARNING: PHAssetResourceRequestOptions is a stub. To generate bindings for this class, include +/// PHAssetResourceRequestOptions in your config's objc-interfaces list. +/// +/// PHAssetResourceRequestOptions +extension type PHAssetResourceRequestOptions._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHAssetResourceRequestOptions] that points to the same underlying object as [other]. + PHAssetResourceRequestOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAssetResourceRequestOptions', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + } + + /// Constructs a [PHAssetResourceRequestOptions] that wraps the given raw object pointer. + PHAssetResourceRequestOptions.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAssetResourceRequestOptions', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + } +} + +late final _class_PHAssetResourceManager = objc.getClass( + "PHAssetResourceManager", +); +late final _class_PHAssetResource = objc.getClass("PHAssetResource"); +late final _sel_originalFilename = objc.registerName("originalFilename"); +late final _sel_assetResourcesForAsset_ = objc.registerName( + "assetResourcesForAsset:", +); + +/// PHAssetResource +extension type PHAssetResource._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHAssetResource] that points to the same underlying object as [other]. + PHAssetResource.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAssetResource', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHAssetResource] that wraps the given raw object pointer. + PHAssetResource.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAssetResource', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHAssetResource]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHAssetResource, + ); + + /// assetResourcesForAsset: + static objc.NSArray assetResourcesForAsset(PHAsset asset) { + objc.checkOsVersionInternal( + 'PHAssetResource.assetResourcesForAsset:', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _class_PHAssetResource, + _sel_assetResourcesForAsset_, + asset.ref.pointer, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } +} + +extension PHAssetResource$Methods on PHAssetResource { + /// originalFilename + objc.NSString get originalFilename { + objc.checkOsVersionInternal( + 'PHAssetResource.originalFilename', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_originalFilename, + ); + return objc.NSString.fromPointer($ret, retain: true, release: true); + } +} + +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSData { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock fromPointer( + ffi.Pointer pointer, { + bool retain = false, + bool release = false, + }) => objc.ObjCBlock( + pointer, + retain: retain, + release: release, + ); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer arg0) + > + > + ptr, + ) => objc.ObjCBlock( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock fromFunction( + void Function(objc.NSData) fn, { + bool keepIsolateAlive = true, + }) => objc.ObjCBlock( + objc.newClosureBlock( + _closureCallable, + (ffi.Pointer arg0) => + fn(objc.NSData.fromPointer(arg0, retain: true, release: true)), + keepIsolateAlive, + ), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This is based on FFI's NativeCallable.listener, and has the same + /// capabilities and limitations. This block can be invoked from any thread, + /// but only supports void functions, and is not run synchronously. See + /// NativeCallable.listener for more details. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock listener( + void Function(objc.NSData) fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _listenerCallable.nativeFunction.cast(), + (ffi.Pointer arg0) => + fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapListenerBlock_xtuoz7(raw); + objc.objectRelease(raw.cast()); + return objc.ObjCBlock( + wrapper, + retain: false, + release: true, + ); + } + + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock blocking( + void Function(objc.NSData) fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _blockingCallable.nativeFunction.cast(), + (ffi.Pointer arg0) => + fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), + keepIsolateAlive, + ); + final rawListener = objc.newClosureBlock( + _blockingListenerCallable.nativeFunction.cast(), + (ffi.Pointer arg0) => + fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapBlockingBlock_xtuoz7( + raw, + rawListener, + objc.objCContext, + ); + objc.objectRelease(raw.cast()); + objc.objectRelease(rawListener.cast()); + return objc.ObjCBlock( + wrapper, + retain: false, + release: true, + ); + } + + static void _listenerTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) { + (objc.getBlockClosure(block) + as void Function(ffi.Pointer))(arg0); + objc.objectRelease(block.cast()); + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + > + _listenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + >.listener(_listenerTrampoline) + ..keepIsolateAlive = false; + static void _blockingTrampoline( + ffi.Pointer block, + ffi.Pointer waiter, + ffi.Pointer arg0, + ) { + try { + (objc.getBlockClosure(block) + as void Function(ffi.Pointer))(arg0); + } catch (e) { + } finally { + objc.signalWaiter(waiter); + objc.objectRelease(block.cast()); + } + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + _blockingCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >.isolateLocal(_blockingTrampoline) + ..keepIsolateAlive = false; + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + _blockingListenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >.listener(_blockingTrampoline) + ..keepIsolateAlive = false; + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => block.ref.target + .cast< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer arg0) + > + >() + .asFunction)>()(arg0); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => + (objc.getBlockClosure(block) + as void Function(ffi.Pointer))(arg0); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + >(_closureTrampoline) + .cast(); +} + +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSData$CallExtension + on objc.ObjCBlock { + void call(objc.NSData arg0) => ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ) + >()(ref.pointer, arg0.ref.pointer); +} + +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSError { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock fromPointer( + ffi.Pointer pointer, { + bool retain = false, + bool release = false, + }) => objc.ObjCBlock( + pointer, + retain: retain, + release: release, + ); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer arg0) + > + > + ptr, + ) => objc.ObjCBlock( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock fromFunction( + void Function(objc.NSError?) fn, { + bool keepIsolateAlive = true, + }) => objc.ObjCBlock( + objc.newClosureBlock( + _closureCallable, + (ffi.Pointer arg0) => fn( + arg0.address == 0 + ? null + : objc.NSError.fromPointer(arg0, retain: true, release: true), + ), + keepIsolateAlive, + ), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This is based on FFI's NativeCallable.listener, and has the same + /// capabilities and limitations. This block can be invoked from any thread, + /// but only supports void functions, and is not run synchronously. See + /// NativeCallable.listener for more details. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock listener( + void Function(objc.NSError?) fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _listenerCallable.nativeFunction.cast(), + (ffi.Pointer arg0) => fn( + arg0.address == 0 + ? null + : objc.NSError.fromPointer(arg0, retain: false, release: true), + ), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapListenerBlock_xtuoz7(raw); + objc.objectRelease(raw.cast()); + return objc.ObjCBlock( + wrapper, + retain: false, + release: true, + ); + } + + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock blocking( + void Function(objc.NSError?) fn, { + bool keepIsolateAlive = true, + }) { + final raw = objc.newClosureBlock( + _blockingCallable.nativeFunction.cast(), + (ffi.Pointer arg0) => fn( + arg0.address == 0 + ? null + : objc.NSError.fromPointer(arg0, retain: false, release: true), + ), + keepIsolateAlive, + ); + final rawListener = objc.newClosureBlock( + _blockingListenerCallable.nativeFunction.cast(), + (ffi.Pointer arg0) => fn( + arg0.address == 0 + ? null + : objc.NSError.fromPointer(arg0, retain: false, release: true), + ), + keepIsolateAlive, + ); + final wrapper = _FoundationFFI_wrapBlockingBlock_xtuoz7( + raw, + rawListener, + objc.objCContext, + ); + objc.objectRelease(raw.cast()); + objc.objectRelease(rawListener.cast()); + return objc.ObjCBlock( + wrapper, + retain: false, + release: true, + ); + } + + static void _listenerTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) { + (objc.getBlockClosure(block) + as void Function(ffi.Pointer))(arg0); + objc.objectRelease(block.cast()); + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + > + _listenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + >.listener(_listenerTrampoline) + ..keepIsolateAlive = false; + static void _blockingTrampoline( + ffi.Pointer block, + ffi.Pointer waiter, + ffi.Pointer arg0, + ) { + try { + (objc.getBlockClosure(block) + as void Function(ffi.Pointer))(arg0); + } catch (e) { + } finally { + objc.signalWaiter(waiter); + objc.objectRelease(block.cast()); + } + } + + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + _blockingCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >.isolateLocal(_blockingTrampoline) + ..keepIsolateAlive = false; + static ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + _blockingListenerCallable = + ffi.NativeCallable< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >.listener(_blockingTrampoline) + ..keepIsolateAlive = false; + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => block.ref.target + .cast< + ffi.NativeFunction< + ffi.Void Function(ffi.Pointer arg0) + > + >() + .asFunction)>()(arg0); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => + (objc.getBlockClosure(block) + as void Function(ffi.Pointer))(arg0); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ) + >(_closureTrampoline) + .cast(); +} + +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSError$CallExtension + on objc.ObjCBlock { + void call(objc.NSError? arg0) => ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ) + >()(ref.pointer, arg0?.ref.pointer ?? ffi.nullptr); +} + +late final _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_ = + objc.registerName( + "requestDataForAssetResource:options:dataReceivedHandler:completionHandler:", + ); +final _objc_msgSend_p4k360 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// PHAssetResourceManager +extension type PHAssetResourceManager._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHAssetResourceManager] that points to the same underlying object as [other]. + PHAssetResourceManager.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAssetResourceManager', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHAssetResourceManager] that wraps the given raw object pointer. + PHAssetResourceManager.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAssetResourceManager', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [PHAssetResourceManager]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_PHAssetResourceManager, + ); + + /// defaultManager + static PHAssetResourceManager defaultManager() { objc.checkOsVersionInternal( - 'PHImageManager.defaultManager', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), + 'PHAssetResourceManager.defaultManager', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); final $ret = _objc_msgSend_151sglz( - _class_PHImageManager, + _class_PHAssetResourceManager, _sel_defaultManager, ); - return PHImageManager.fromPointer($ret, retain: true, release: true); + return PHAssetResourceManager.fromPointer( + $ret, + retain: true, + release: true, + ); } } -extension PHImageManager$Methods on PHImageManager { - /// @abstract Request largest represented image as data bytes and EXIF orientation for the specified asset. - /// @param asset The asset whose image data is to be loaded. - /// @param options Options specifying how Photos should handle the request, format the requested image, and notify your app of progress or errors. - /// If PHImageRequestOptionsVersionCurrent is requested and the asset has adjustments then the largest rendered image data is returned. In all other cases then the original image data is returned. - /// @param resultHandler A block that is called exactly once either synchronously on the current thread or asynchronously on the main thread depending on the synchronous option specified in the PHImageRequestOptions options parameter (deliveryMode is ignored). Orientation is an EXIF orientation as an CGImagePropertyOrientation. For iOS or tvOS, convert this to an UIImageOrientation. - int requestImageDataAndOrientationForAsset( - PHAsset asset, { - PHImageRequestOptions? options, - required objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) - > - resultHandler, +extension PHAssetResourceManager$Methods on PHAssetResourceManager { + /// requestDataForAssetResource:options:dataReceivedHandler:completionHandler: + int requestDataForAssetResource( + PHAssetResource resource, { + PHAssetResourceRequestOptions? options, + required objc.ObjCBlock dataReceivedHandler, + required objc.ObjCBlock completionHandler, }) { objc.checkOsVersionInternal( - 'PHImageManager.requestImageDataAndOrientationForAsset:options:resultHandler:', - iOS: (false, (13, 0, 0)), + 'PHAssetResourceManager.requestDataForAssetResource:options:dataReceivedHandler:completionHandler:', + iOS: (false, (9, 0, 0)), macOS: (false, (10, 15, 0)), ); - return _objc_msgSend_1urj8nv( + return _objc_msgSend_p4k360( object$.ref.pointer, - _sel_requestImageDataAndOrientationForAsset_options_resultHandler_, - asset.ref.pointer, + _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_, + resource.ref.pointer, options?.ref.pointer ?? ffi.nullptr, - resultHandler.ref.pointer, + dataReceivedHandler.ref.pointer, + completionHandler.ref.pointer, ); } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m index 6eef5f92fbad..9a0ff00dea39 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m @@ -1,9 +1,7 @@ #include #import #import -#import -#import -#import +#import #if !__has_feature(objc_arc) #error "This file must be compiled with ARC enabled" @@ -51,19 +49,42 @@ }; -typedef void (^_ListenerTrampoline)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +typedef void (^_ListenerTrampoline)(id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _FoundationFFI_wrapListenerBlock_10c3wkj(_ListenerTrampoline block) NS_RETURNS_RETAINED { +_ListenerTrampoline _FoundationFFI_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { + return ^void(id arg0, id arg1) { + objc_retainBlock(block); + block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + }; +} + +typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline _FoundationFFI_wrapBlockingBlock_pfv6jd( + _BlockingTrampoline block, _BlockingTrampoline listenerBlock, + DOBJC_Context* ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1), { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + }, { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + }); +} + +typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_1 _FoundationFFI_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { objc_retainBlock(block); block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); }; } -typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +typedef void (^_BlockingTrampoline_1)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _FoundationFFI_wrapBlockingBlock_10c3wkj( - _BlockingTrampoline block, _BlockingTrampoline listenerBlock, +_ListenerTrampoline_1 _FoundationFFI_wrapBlockingBlock_10c3wkj( + _BlockingTrampoline_1 block, _BlockingTrampoline_1 listenerBlock, DOBJC_Context* ctx) NS_RETURNS_RETAINED { BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { objc_retainBlock(block); @@ -73,6 +94,29 @@ _ListenerTrampoline _FoundationFFI_wrapBlockingBlock_10c3wkj( listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); }); } + +typedef void (^_ListenerTrampoline_2)(id arg0); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_2 _FoundationFFI_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { + return ^void(id arg0) { + objc_retainBlock(block); + block((__bridge id)(__bridge_retained void*)(arg0)); + }; +} + +typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_2 _FoundationFFI_wrapBlockingBlock_xtuoz7( + _BlockingTrampoline_2 block, _BlockingTrampoline_2 listenerBlock, + DOBJC_Context* ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0), { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void*)(arg0)); + }, { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0)); + }); +} #undef BLOCKING_BLOCK_IMPL #pragma clang diagnostic pop diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index d93be6618e5e..fede8663a5e1 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -18,26 +18,8 @@ void main() { ), headers: Headers( entryPoints: [ - // Uri.file( - // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/Photos.h', - // ), - // Uri.file( - // '$macSdkPath/System/Library/Frameworks/Foundation.framework/Headers/NSFileManager.h', - // ), Uri.file( - '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAsset.h', - ), - Uri.file( - '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResource.h', - ), - // Uri.file( - // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHAssetResourceManager.h', - // ), - // Uri.file( - // '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHFetchResult.h', - // ), - Uri.file( - '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/PHImageManager.h', + '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/Photos.h', ), ], compilerOptions: ['-include stdint.h'], @@ -49,17 +31,13 @@ void main() { 'NSFileManager', 'PHAsset', 'PHAssetResource', - // 'PHAssetResourceManager', + 'PHAssetResourceManager', 'PHFetchResult', 'PHImageManager', 'PHImageRequestOptions', }.contains(declaration.originalName); }, includeMember: (Declaration declaration, String member) { - if (declaration.originalName == 'PHAssetResource' && - member.contains('assetResources')) { - print('APPLE: $member'); - } final String interfaceName = declaration.originalName; final signature = member; return switch (interfaceName) { @@ -75,6 +53,10 @@ void main() { 'assetResourcesForAsset:', 'originalFilename', }.contains(signature), + 'PHAssetResourceManager' => { + 'defaultManager', + 'requestDataForAssetResource:options:dataReceivedHandler:completionHandler:', + }.contains(signature), 'PHFetchResult' => {'firstObject'}.contains(signature), 'PHImageManager' => { 'defaultManager', @@ -87,16 +69,6 @@ void main() { }; }, ), - // categories: Categories( - // include: (Declaration declaration) => { - // // For URLByAppendingPathComponent: - // 'NSURLPathUtilities', - // }.contains(declaration.originalName), - // includeTransitive: false, - // ), ), - // functions: Functions.includeSet({ - // 'NSSearchPathForDirectoriesInDomains', - // }), ).generate(); } From eab82fc37cdf39bb3aeb456320ae9fc1dcb1c2e1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 13:53:46 -0400 Subject: [PATCH 269/398] add dynamic library --- .../lib/src/cross_file_darwin.dart | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index e3c62fb44bd0..8324bdd9da47 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -2,18 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:ffi' as ffi; + import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'darwin_scoped_storage_cross_directory.dart'; import 'darwin_scoped_storage_cross_file.dart'; -import 'ffi_bindings.g.dart'; /// Implementation of [CrossFilePlatform] for iOS and macOS. base class CrossFileDarwin extends CrossFileIO { /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileDarwin(); + ffi.DynamicLibrary.open( + '/System/Library/Frameworks/Photos.framework/Versions/Current/Photos', + ); } /// Whether the current implementation of `cross_file` is [CrossFileDarwin]. @@ -34,14 +38,3 @@ base class CrossFileDarwin extends CrossFileIO { return DarwinScopedStorageXDirectory(params); } } - -// final ffi.DynamicLibrary _dylib = () { -// return ffi.DynamicLibrary.open( -// '/System/Library/Frameworks/Foundation.framework/Foundation', -// ); -// }(); - -// /// The bindings to the native functions in [_dylib]. -// final FoundationFFI _lib = () { -// return FoundationFFI(_dylib); -// }(); From d43a862cc49372d92efed148bdab8f9bc6d2d970 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:38:22 -0400 Subject: [PATCH 270/398] wire up most of it --- ...darwin_scoped_storage_cross_directory.dart | 1 - .../src/darwin_scoped_storage_cross_file.dart | 121 +- .../lib/src/ffi_bindings.g.dart | 3473 ++++++++++++++++- .../cross_file_darwin/tool/ffigen.dart | 8 +- 4 files changed, 3465 insertions(+), 138 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 5d5d13ac1264..cfdcf01ef436 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -9,7 +9,6 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'package:flutter/foundation.dart'; import 'package:objective_c/objective_c.dart'; -import 'cross_file_darwin_apis.g.dart'; import 'darwin_scoped_storage_cross_file.dart'; import 'ffi_bindings.g.dart'; import 'security_scoped_resource.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index b96643b05f93..efc95992d3bf 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -4,19 +4,17 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:ffi' as ffi; +import 'dart:ffi'; import 'dart:io'; - -import 'package:objective_c/objective_c.dart'; +import 'dart:ui'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart'; +import 'package:objective_c/objective_c.dart'; import 'package:path/path.dart' as path; -import 'cross_file_darwin_apis.g.dart'; -import 'security_scoped_resource.dart'; - import 'ffi_bindings.g.dart'; +import 'security_scoped_resource.dart'; /// Base implementation of [PlatformScopedStorageXFileCreationParams] for iOS /// and macOS. @@ -29,8 +27,7 @@ sealed class DarwinScopedStorageXFileCreationParams /// scoped uri. factory DarwinScopedStorageXFileCreationParams.securityScoped({ required String uri, - }) => - SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri); + }) => SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri); /// Constructs a [DarwinScopedStorageXFileCreationParams] with an asset /// identifier from the Photos Library. @@ -193,16 +190,34 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile @override Future lastModified() async { - throw UnsupportedError(''); + if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { + final NSDate? date = asset.modificationDate; + if (date != null) { + DateTime.fromMillisecondsSinceEpoch( + (date.timeIntervalSince1970 * 1000).round(), + ); + } + } + + return null; } @override Future length() async { - try { - throw UnsupportedError(''); - } on FileSystemException { - return null; + if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { + final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); + final ObjCObject? firstObject = resources.firstObject; + + if (firstObject != null) { + final PHAssetResource resource = PHAssetResource.as(firstObject); + final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); + print(fileSize); + + return null; + } } + + return null; } @override @@ -210,11 +225,45 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile throw UnsupportedError(''); @override - Future readAsBytes() => throw UnsupportedError(''); + Future readAsBytes() { + if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { + final PHImageManager manager = PHImageManager.defaultManager(); + final PHImageRequestOptions options = PHImageRequestOptions.new$(); + options.isNetworkAccessAllowed = true; + + final bytesCompleter = Completer(); + void resultHandler( + NSData? imageData, + NSString? dataUti, + CGImagePropertyOrientation orientation, + NSDictionary? info, + ) { + if (imageData != null) { + runOnPlatformThread(() { + final Uint8List bytes = _extractBytesToUint8List(imageData); + bytesCompleter.complete(bytes); + }); + } + } + + manager.requestImageDataAndOrientationForAsset( + asset, + options: options, + resultHandler: + ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary.listener( + resultHandler, + ), + ); + return bytesCompleter.future; + } + + throw Error(); + } @override - Future readAsString({Encoding encoding = utf8}) => - throw UnsupportedError(''); + Future readAsString({Encoding encoding = utf8}) async { + return encoding.decode(await readAsBytes()); + } @override Future canRead() { @@ -222,10 +271,46 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } @override - Future exists() async => throw UnsupportedError(''); + Future exists() async => _tryGetAsset(identifier: params.uri) != null; @override - Future name() async => throw UnsupportedError(''); + Future name() async { + if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { + final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); + final ObjCObject? firstObject = resources.firstObject; + + if (firstObject != null) { + final PHAssetResource resource = PHAssetResource.as(firstObject); + return resource.originalFilename.toDartString(); + } + } + + return null; + } + + PHAsset? _tryGetAsset({required String identifier}) { + final PHFetchResult result = PHAsset.fetchAssetsWithLocalIdentifiers( + [params.uri].toNSArray(), + ); + final ObjCObject? firstObject = result.firstObject; + if (firstObject != null) { + return PHAsset.as(firstObject); + } + + return null; + } + + Uint8List _extractBytesToUint8List(NSData data) { + int length = data.length; + + if (length == 0) { + return Uint8List(0); + } + + final Pointer uint8Pointer = data.bytes.cast(); + final Uint8List byteView = uint8Pointer.asTypedList(length); + return Uint8List.fromList(byteView); + } } /// Provides platform specific features for diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 76347bdc2678..6d33ecf03494 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -66,32 +66,2665 @@ _FoundationFFI_wrapBlockingBlock_xtuoz7( ffi.Pointer context, ); +late final _class_NSObject = objc.getClass("NSObject"); +late final _sel_version = objc.registerName("version"); +final _objc_msgSend_1hz7y9r = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Long Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_setVersion_ = objc.registerName("setVersion:"); +final _objc_msgSend_4sp4xj = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Long, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ) + >(); +late final _sel_classForCoder = objc.registerName("classForCoder"); +final _objc_msgSend_151sglz = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_replacementObjectForCoder_ = objc.registerName( + "replacementObjectForCoder:", +); +final _objc_msgSend_1sotr3r = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_awakeAfterUsingCoder_ = objc.registerName( + "awakeAfterUsingCoder:", +); + +/// NSCoderMethods +extension NSCoderMethods on objc.NSObject { + /// awakeAfterUsingCoder: + objc.ObjCObject? awakeAfterUsingCoder(objc.NSCoder coder) { + objc.checkOsVersionInternal( + 'NSObject.awakeAfterUsingCoder:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.retainAndReturnPointer(), + _sel_awakeAfterUsingCoder_, + coder.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: false, release: true); + } + + /// classForCoder + objc.ObjCObject get classForCoder { + objc.checkOsVersionInternal( + 'NSObject.classForCoder', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForCoder); + return objc.ObjCObject($ret, retain: true, release: true); + } + + /// replacementObjectForCoder: + objc.ObjCObject? replacementObjectForCoder(objc.NSCoder coder) { + objc.checkOsVersionInternal( + 'NSObject.replacementObjectForCoder:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_replacementObjectForCoder_, + coder.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// setVersion: + static void setVersion(int aVersion) { + objc.checkOsVersionInternal( + 'NSObject.setVersion:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_4sp4xj(_class_NSObject, _sel_setVersion_, aVersion); + } + + /// version + static int version() { + objc.checkOsVersionInternal( + 'NSObject.version', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_1hz7y9r(_class_NSObject, _sel_version); + } +} + +late final _sel_poseAsClass_ = objc.registerName("poseAsClass:"); +final _objc_msgSend_xtuoz7 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// NSDeprecatedMethods +extension NSDeprecatedMethods on objc.NSObject { + /// poseAsClass: + static void poseAsClass(objc.ObjCObject aClass) { + objc.checkOsVersionInternal( + 'NSObject.poseAsClass:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + _class_NSObject, + _sel_poseAsClass_, + aClass.ref.pointer, + ); + } +} + +late final _sel_autoContentAccessingProxy = objc.registerName( + "autoContentAccessingProxy", +); + +/// NSDiscardableContentProxy +extension NSDiscardableContentProxy on objc.NSObject { + /// autoContentAccessingProxy + objc.ObjCObject get autoContentAccessingProxy { + objc.checkOsVersionInternal( + 'NSObject.autoContentAccessingProxy', + iOS: (false, (4, 0, 0)), + macOS: (false, (10, 6, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_autoContentAccessingProxy, + ); + return objc.ObjCObject($ret, retain: true, release: true); + } +} + +late final _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_ = + objc.registerName( + "attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:", + ); +final _objc_msgSend_10txwc9 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_attemptRecoveryFromError_optionIndex_ = objc.registerName( + "attemptRecoveryFromError:optionIndex:", +); +final _objc_msgSend_z7gxsm = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ) + >(); + +/// NSErrorRecoveryAttempting +extension NSErrorRecoveryAttempting on objc.NSObject { + /// attemptRecoveryFromError:optionIndex: + bool attemptRecoveryFromError( + objc.NSError error, { + required int optionIndex, + }) { + objc.checkOsVersionInternal( + 'NSObject.attemptRecoveryFromError:optionIndex:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_z7gxsm( + object$.ref.pointer, + _sel_attemptRecoveryFromError_optionIndex_, + error.ref.pointer, + optionIndex, + ); + } + + /// attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo: + void attemptRecoveryFromError$1( + objc.NSError error, { + required int optionIndex, + objc.ObjCObject? delegate, + required ffi.Pointer didRecoverSelector, + required ffi.Pointer contextInfo, + }) { + objc.checkOsVersionInternal( + 'NSObject.attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_10txwc9( + object$.ref.pointer, + _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_, + error.ref.pointer, + optionIndex, + delegate?.ref.pointer ?? ffi.nullptr, + didRecoverSelector, + contextInfo, + ); + } +} + +late final _sel_performSelector_withObject_afterDelay_inModes_ = objc + .registerName("performSelector:withObject:afterDelay:inModes:"); +final _objc_msgSend_t8ajot = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Double, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + double, + ffi.Pointer, + ) + >(); +late final _sel_performSelector_withObject_afterDelay_ = objc.registerName( + "performSelector:withObject:afterDelay:", +); +final _objc_msgSend_7ql5kn = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Double, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + double, + ) + >(); +late final _sel_cancelPreviousPerformRequestsWithTarget_selector_object_ = objc + .registerName("cancelPreviousPerformRequestsWithTarget:selector:object:"); +final _objc_msgSend_1ygbbzi = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_cancelPreviousPerformRequestsWithTarget_ = objc.registerName( + "cancelPreviousPerformRequestsWithTarget:", +); + +/// NSDelayedPerforming +extension NSDelayedPerforming on objc.NSObject { + /// performSelector:withObject:afterDelay: + void performSelector( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required double afterDelay, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelector:withObject:afterDelay:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_7ql5kn( + object$.ref.pointer, + _sel_performSelector_withObject_afterDelay_, + aSelector, + withObject?.ref.pointer ?? ffi.nullptr, + afterDelay, + ); + } + + /// performSelector:withObject:afterDelay:inModes: + void performSelector$1( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required double afterDelay, + required objc.NSArray inModes, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelector:withObject:afterDelay:inModes:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_t8ajot( + object$.ref.pointer, + _sel_performSelector_withObject_afterDelay_inModes_, + aSelector, + withObject?.ref.pointer ?? ffi.nullptr, + afterDelay, + inModes.ref.pointer, + ); + } + + /// cancelPreviousPerformRequestsWithTarget: + static void cancelPreviousPerformRequestsWithTarget(objc.ObjCObject aTarget) { + objc.checkOsVersionInternal( + 'NSObject.cancelPreviousPerformRequestsWithTarget:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + _class_NSObject, + _sel_cancelPreviousPerformRequestsWithTarget_, + aTarget.ref.pointer, + ); + } + + /// cancelPreviousPerformRequestsWithTarget:selector:object: + static void cancelPreviousPerformRequestsWithTarget$1( + objc.ObjCObject aTarget, { + required ffi.Pointer selector, + objc.ObjCObject? object, + }) { + objc.checkOsVersionInternal( + 'NSObject.cancelPreviousPerformRequestsWithTarget:selector:object:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1ygbbzi( + _class_NSObject, + _sel_cancelPreviousPerformRequestsWithTarget_selector_object_, + aTarget.ref.pointer, + selector, + object?.ref.pointer ?? ffi.nullptr, + ); + } +} + +late final _sel_URL_resourceDataDidBecomeAvailable_ = objc.registerName( + "URL:resourceDataDidBecomeAvailable:", +); +final _objc_msgSend_pfv6jd = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_URLResourceDidFinishLoading_ = objc.registerName( + "URLResourceDidFinishLoading:", +); +late final _sel_URLResourceDidCancelLoading_ = objc.registerName( + "URLResourceDidCancelLoading:", +); +late final _sel_URL_resourceDidFailLoadingWithReason_ = objc.registerName( + "URL:resourceDidFailLoadingWithReason:", +); + +/// NSURLClient +extension NSURLClient on objc.NSObject { + /// URL:resourceDataDidBecomeAvailable: + void URL( + objc.NSURL sender, { + required objc.NSData resourceDataDidBecomeAvailable, + }) { + objc.checkOsVersionInternal( + 'NSObject.URL:resourceDataDidBecomeAvailable:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_URL_resourceDataDidBecomeAvailable_, + sender.ref.pointer, + resourceDataDidBecomeAvailable.ref.pointer, + ); + } + + /// URL:resourceDidFailLoadingWithReason: + void URL$1( + objc.NSURL sender, { + required objc.NSString resourceDidFailLoadingWithReason, + }) { + objc.checkOsVersionInternal( + 'NSObject.URL:resourceDidFailLoadingWithReason:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_URL_resourceDidFailLoadingWithReason_, + sender.ref.pointer, + resourceDidFailLoadingWithReason.ref.pointer, + ); + } + + /// URLResourceDidCancelLoading: + void URLResourceDidCancelLoading(objc.NSURL sender) { + objc.checkOsVersionInternal( + 'NSObject.URLResourceDidCancelLoading:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_URLResourceDidCancelLoading_, + sender.ref.pointer, + ); + } + + /// URLResourceDidFinishLoading: + void URLResourceDidFinishLoading(objc.NSURL sender) { + objc.checkOsVersionInternal( + 'NSObject.URLResourceDidFinishLoading:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_URLResourceDidFinishLoading_, + sender.ref.pointer, + ); + } +} + late final _class_NSFileManager = objc.getClass("NSFileManager"); late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:"); final _objc_msgSend_19nvye5 = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.Bool Function( + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_defaultManager = objc.registerName("defaultManager"); +late final _sel_isReadableFileAtPath_ = objc.registerName( + "isReadableFileAtPath:", +); +late final _sel_homeDirectoryForCurrentUser = objc.registerName( + "homeDirectoryForCurrentUser", +); +late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); +late final _sel_homeDirectoryForUser_ = objc.registerName( + "homeDirectoryForUser:", +); + +/// NSUserInformation +extension NSUserInformation on NSFileManager { + /// homeDirectoryForCurrentUser + objc.NSURL get homeDirectoryForCurrentUser { + objc.checkOsVersionInternal( + 'NSFileManager.homeDirectoryForCurrentUser', + iOS: (true, null), + macOS: (false, (10, 12, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_homeDirectoryForCurrentUser, + ); + return objc.NSURL.fromPointer($ret, retain: true, release: true); + } + + /// homeDirectoryForUser: + objc.NSURL? homeDirectoryForUser(objc.NSString userName) { + objc.checkOsVersionInternal( + 'NSFileManager.homeDirectoryForUser:', + iOS: (true, null), + macOS: (false, (10, 12, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_homeDirectoryForUser_, + userName.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.NSURL.fromPointer($ret, retain: true, release: true); + } + + /// temporaryDirectory + objc.NSURL get temporaryDirectory { + objc.checkOsVersionInternal( + 'NSFileManager.temporaryDirectory', + iOS: (false, (10, 0, 0)), + macOS: (false, (10, 12, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_temporaryDirectory, + ); + return objc.NSURL.fromPointer($ret, retain: true, release: true); + } +} + +/// NSFileManager +extension type NSFileManager._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSFileManager] that points to the same underlying object as [other]. + NSFileManager.as(objc.ObjCObject other) : object$ = other { + assert(isA(object$)); + } + + /// Constructs a [NSFileManager] that wraps the given raw object pointer. + NSFileManager.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [NSFileManager]. + static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( + obj.ref.pointer, + _sel_isKindOfClass_, + _class_NSFileManager, + ); + + /// defaultManager + static NSFileManager getDefaultManager() { + final $ret = _objc_msgSend_151sglz( + _class_NSFileManager, + _sel_defaultManager, + ); + return NSFileManager.fromPointer($ret, retain: true, release: true); + } +} + +extension NSFileManager$Methods on NSFileManager { + /// isReadableFileAtPath: + bool isReadableFileAtPath(objc.NSString path) { + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isReadableFileAtPath_, + path.ref.pointer, + ); + } +} + +late final _sel_fileManager_shouldProceedAfterError_ = objc.registerName( + "fileManager:shouldProceedAfterError:", +); +final _objc_msgSend_1lsax7n = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_fileManager_willProcessPath_ = objc.registerName( + "fileManager:willProcessPath:", +); + +/// NSCopyLinkMoveHandler +extension NSCopyLinkMoveHandler on objc.NSObject { + /// fileManager:shouldProceedAfterError: + bool fileManager( + NSFileManager fm, { + required objc.NSDictionary shouldProceedAfterError, + }) { + objc.checkOsVersionInternal( + 'NSObject.fileManager:shouldProceedAfterError:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_1lsax7n( + object$.ref.pointer, + _sel_fileManager_shouldProceedAfterError_, + fm.ref.pointer, + shouldProceedAfterError.ref.pointer, + ); + } + + /// fileManager:willProcessPath: + void fileManager$1( + NSFileManager fm, { + required objc.NSString willProcessPath, + }) { + objc.checkOsVersionInternal( + 'NSObject.fileManager:willProcessPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_fileManager_willProcessPath_, + fm.ref.pointer, + willProcessPath.ref.pointer, + ); + } +} + +late final _sel_accessInstanceVariablesDirectly = objc.registerName( + "accessInstanceVariablesDirectly", +); +final _objc_msgSend_91o635 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_valueForKey_ = objc.registerName("valueForKey:"); +late final _sel_setValue_forKey_ = objc.registerName("setValue:forKey:"); +late final _sel_validateValue_forKey_error_ = objc.registerName( + "validateValue:forKey:error:", +); +final _objc_msgSend_1j9bhml = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>, + ffi.Pointer, + ffi.Pointer>, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>, + ffi.Pointer, + ffi.Pointer>, + ) + >(); +late final _sel_mutableArrayValueForKey_ = objc.registerName( + "mutableArrayValueForKey:", +); +late final _sel_mutableOrderedSetValueForKey_ = objc.registerName( + "mutableOrderedSetValueForKey:", +); +late final _sel_mutableSetValueForKey_ = objc.registerName( + "mutableSetValueForKey:", +); +late final _sel_valueForKeyPath_ = objc.registerName("valueForKeyPath:"); +late final _sel_setValue_forKeyPath_ = objc.registerName( + "setValue:forKeyPath:", +); +late final _sel_validateValue_forKeyPath_error_ = objc.registerName( + "validateValue:forKeyPath:error:", +); +late final _sel_mutableArrayValueForKeyPath_ = objc.registerName( + "mutableArrayValueForKeyPath:", +); +late final _sel_mutableOrderedSetValueForKeyPath_ = objc.registerName( + "mutableOrderedSetValueForKeyPath:", +); +late final _sel_mutableSetValueForKeyPath_ = objc.registerName( + "mutableSetValueForKeyPath:", +); +late final _sel_valueForUndefinedKey_ = objc.registerName( + "valueForUndefinedKey:", +); +late final _sel_setValue_forUndefinedKey_ = objc.registerName( + "setValue:forUndefinedKey:", +); +late final _sel_setNilValueForKey_ = objc.registerName("setNilValueForKey:"); +late final _sel_dictionaryWithValuesForKeys_ = objc.registerName( + "dictionaryWithValuesForKeys:", +); +late final _sel_setValuesForKeysWithDictionary_ = objc.registerName( + "setValuesForKeysWithDictionary:", +); + +/// NSKeyValueCoding +extension NSKeyValueCoding on objc.NSObject { + /// dictionaryWithValuesForKeys: + objc.NSDictionary dictionaryWithValuesForKeys(objc.NSArray keys) { + objc.checkOsVersionInternal( + 'NSObject.dictionaryWithValuesForKeys:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_dictionaryWithValuesForKeys_, + keys.ref.pointer, + ); + return objc.NSDictionary.fromPointer($ret, retain: true, release: true); + } + + /// mutableArrayValueForKey: + objc.NSMutableArray mutableArrayValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.mutableArrayValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_mutableArrayValueForKey_, + key.ref.pointer, + ); + return objc.NSMutableArray.fromPointer($ret, retain: true, release: true); + } + + /// mutableArrayValueForKeyPath: + objc.NSMutableArray mutableArrayValueForKeyPath(objc.NSString keyPath) { + objc.checkOsVersionInternal( + 'NSObject.mutableArrayValueForKeyPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_mutableArrayValueForKeyPath_, + keyPath.ref.pointer, + ); + return objc.NSMutableArray.fromPointer($ret, retain: true, release: true); + } + + /// mutableOrderedSetValueForKey: + objc.NSMutableOrderedSet mutableOrderedSetValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.mutableOrderedSetValueForKey:', + iOS: (false, (5, 0, 0)), + macOS: (false, (10, 7, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_mutableOrderedSetValueForKey_, + key.ref.pointer, + ); + return objc.NSMutableOrderedSet.fromPointer( + $ret, + retain: true, + release: true, + ); + } + + /// mutableOrderedSetValueForKeyPath: + objc.NSMutableOrderedSet mutableOrderedSetValueForKeyPath( + objc.NSString keyPath, + ) { + objc.checkOsVersionInternal( + 'NSObject.mutableOrderedSetValueForKeyPath:', + iOS: (false, (5, 0, 0)), + macOS: (false, (10, 7, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_mutableOrderedSetValueForKeyPath_, + keyPath.ref.pointer, + ); + return objc.NSMutableOrderedSet.fromPointer( + $ret, + retain: true, + release: true, + ); + } + + /// mutableSetValueForKey: + objc.NSMutableSet mutableSetValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.mutableSetValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_mutableSetValueForKey_, + key.ref.pointer, + ); + return objc.NSMutableSet.fromPointer($ret, retain: true, release: true); + } + + /// mutableSetValueForKeyPath: + objc.NSMutableSet mutableSetValueForKeyPath(objc.NSString keyPath) { + objc.checkOsVersionInternal( + 'NSObject.mutableSetValueForKeyPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_mutableSetValueForKeyPath_, + keyPath.ref.pointer, + ); + return objc.NSMutableSet.fromPointer($ret, retain: true, release: true); + } + + /// setNilValueForKey: + void setNilValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.setNilValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_setNilValueForKey_, + key.ref.pointer, + ); + } + + /// setValue:forKey: + void setValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + objc.checkOsVersionInternal( + 'NSObject.setValue:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_setValue_forKey_, + value?.ref.pointer ?? ffi.nullptr, + forKey.ref.pointer, + ); + } + + /// setValue:forKeyPath: + void setValue$1(objc.ObjCObject? value, {required objc.NSString forKeyPath}) { + objc.checkOsVersionInternal( + 'NSObject.setValue:forKeyPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_setValue_forKeyPath_, + value?.ref.pointer ?? ffi.nullptr, + forKeyPath.ref.pointer, + ); + } + + /// setValue:forUndefinedKey: + void setValue$2( + objc.ObjCObject? value, { + required objc.NSString forUndefinedKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.setValue:forUndefinedKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_setValue_forUndefinedKey_, + value?.ref.pointer ?? ffi.nullptr, + forUndefinedKey.ref.pointer, + ); + } + + /// setValuesForKeysWithDictionary: + void setValuesForKeysWithDictionary(objc.NSDictionary keyedValues) { + objc.checkOsVersionInternal( + 'NSObject.setValuesForKeysWithDictionary:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_setValuesForKeysWithDictionary_, + keyedValues.ref.pointer, + ); + } + + /// validateValue:forKey:error: + bool validateValue( + ffi.Pointer> ioValue, { + required objc.NSString forKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.validateValue:forKey:error:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $err = pkg_ffi.calloc>(); + try { + final $ret = _objc_msgSend_1j9bhml( + object$.ref.pointer, + _sel_validateValue_forKey_error_, + ioValue, + forKey.ref.pointer, + $err, + ); + objc.NSErrorException.checkErrorPointer($err.value); + return $ret; + } finally { + pkg_ffi.calloc.free($err); + } + } + + /// validateValue:forKeyPath:error: + bool validateValue$1( + ffi.Pointer> ioValue, { + required objc.NSString forKeyPath, + }) { + objc.checkOsVersionInternal( + 'NSObject.validateValue:forKeyPath:error:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $err = pkg_ffi.calloc>(); + try { + final $ret = _objc_msgSend_1j9bhml( + object$.ref.pointer, + _sel_validateValue_forKeyPath_error_, + ioValue, + forKeyPath.ref.pointer, + $err, + ); + objc.NSErrorException.checkErrorPointer($err.value); + return $ret; + } finally { + pkg_ffi.calloc.free($err); + } + } + + /// valueForKey: + objc.ObjCObject? valueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.valueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_valueForKey_, + key.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// valueForKeyPath: + objc.ObjCObject? valueForKeyPath(objc.NSString keyPath) { + objc.checkOsVersionInternal( + 'NSObject.valueForKeyPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_valueForKeyPath_, + keyPath.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// valueForUndefinedKey: + objc.ObjCObject? valueForUndefinedKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.valueForUndefinedKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_valueForUndefinedKey_, + key.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// accessInstanceVariablesDirectly + static bool getAccessInstanceVariablesDirectly() { + objc.checkOsVersionInternal( + 'NSObject.accessInstanceVariablesDirectly', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_91o635( + _class_NSObject, + _sel_accessInstanceVariablesDirectly, + ); + } +} + +late final _sel_useStoredAccessor = objc.registerName("useStoredAccessor"); +late final _sel_storedValueForKey_ = objc.registerName("storedValueForKey:"); +late final _sel_takeStoredValue_forKey_ = objc.registerName( + "takeStoredValue:forKey:", +); +late final _sel_takeValue_forKey_ = objc.registerName("takeValue:forKey:"); +late final _sel_takeValue_forKeyPath_ = objc.registerName( + "takeValue:forKeyPath:", +); +late final _sel_handleQueryWithUnboundKey_ = objc.registerName( + "handleQueryWithUnboundKey:", +); +late final _sel_handleTakeValue_forUnboundKey_ = objc.registerName( + "handleTakeValue:forUnboundKey:", +); +late final _sel_unableToSetNilForKey_ = objc.registerName( + "unableToSetNilForKey:", +); +late final _sel_valuesForKeys_ = objc.registerName("valuesForKeys:"); +late final _sel_takeValuesFromDictionary_ = objc.registerName( + "takeValuesFromDictionary:", +); + +/// NSDeprecatedKeyValueCoding +extension NSDeprecatedKeyValueCoding on objc.NSObject { + /// handleQueryWithUnboundKey: + objc.ObjCObject? handleQueryWithUnboundKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.handleQueryWithUnboundKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_handleQueryWithUnboundKey_, + key.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// handleTakeValue:forUnboundKey: + void handleTakeValue( + objc.ObjCObject? value, { + required objc.NSString forUnboundKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.handleTakeValue:forUnboundKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_handleTakeValue_forUnboundKey_, + value?.ref.pointer ?? ffi.nullptr, + forUnboundKey.ref.pointer, + ); + } + + /// storedValueForKey: + objc.ObjCObject? storedValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.storedValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_storedValueForKey_, + key.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// takeStoredValue:forKey: + void takeStoredValue( + objc.ObjCObject? value, { + required objc.NSString forKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.takeStoredValue:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_takeStoredValue_forKey_, + value?.ref.pointer ?? ffi.nullptr, + forKey.ref.pointer, + ); + } + + /// takeValue:forKey: + void takeValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + objc.checkOsVersionInternal( + 'NSObject.takeValue:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_takeValue_forKey_, + value?.ref.pointer ?? ffi.nullptr, + forKey.ref.pointer, + ); + } + + /// takeValue:forKeyPath: + void takeValue$1( + objc.ObjCObject? value, { + required objc.NSString forKeyPath, + }) { + objc.checkOsVersionInternal( + 'NSObject.takeValue:forKeyPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_takeValue_forKeyPath_, + value?.ref.pointer ?? ffi.nullptr, + forKeyPath.ref.pointer, + ); + } + + /// takeValuesFromDictionary: + void takeValuesFromDictionary(objc.NSDictionary properties) { + objc.checkOsVersionInternal( + 'NSObject.takeValuesFromDictionary:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_takeValuesFromDictionary_, + properties.ref.pointer, + ); + } + + /// unableToSetNilForKey: + void unableToSetNilForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.unableToSetNilForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_unableToSetNilForKey_, + key.ref.pointer, + ); + } + + /// valuesForKeys: + objc.NSDictionary valuesForKeys(objc.NSArray keys) { + objc.checkOsVersionInternal( + 'NSObject.valuesForKeys:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_valuesForKeys_, + keys.ref.pointer, + ); + return objc.NSDictionary.fromPointer($ret, retain: true, release: true); + } + + /// useStoredAccessor + static bool useStoredAccessor() { + objc.checkOsVersionInternal( + 'NSObject.useStoredAccessor', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_91o635(_class_NSObject, _sel_useStoredAccessor); + } +} + +late final _sel_observeValueForKeyPath_ofObject_change_context_ = objc + .registerName("observeValueForKeyPath:ofObject:change:context:"); +final _objc_msgSend_1pl4k3n = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// NSKeyValueObserving +extension NSKeyValueObserving on objc.NSObject { + /// observeValueForKeyPath:ofObject:change:context: + void observeValueForKeyPath( + objc.NSString? keyPath, { + objc.ObjCObject? ofObject, + objc.NSDictionary? change, + required ffi.Pointer context, + }) { + objc.checkOsVersionInternal( + 'NSObject.observeValueForKeyPath:ofObject:change:context:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1pl4k3n( + object$.ref.pointer, + _sel_observeValueForKeyPath_ofObject_change_context_, + keyPath?.ref.pointer ?? ffi.nullptr, + ofObject?.ref.pointer ?? ffi.nullptr, + change?.ref.pointer ?? ffi.nullptr, + context, + ); + } +} + +late final _sel_addObserver_forKeyPath_options_context_ = objc.registerName( + "addObserver:forKeyPath:options:context:", +); +final _objc_msgSend_akk2cd = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +late final _sel_removeObserver_forKeyPath_context_ = objc.registerName( + "removeObserver:forKeyPath:context:", +); +final _objc_msgSend_1jed5jl = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_removeObserver_forKeyPath_ = objc.registerName( + "removeObserver:forKeyPath:", +); + +/// NSKeyValueObserverRegistration +extension NSKeyValueObserverRegistration on objc.NSObject { + /// addObserver:forKeyPath:options:context: + void addObserver( + objc.NSObject observer, { + required objc.NSString forKeyPath, + required int options, + required ffi.Pointer context, + }) { + objc.checkOsVersionInternal( + 'NSObject.addObserver:forKeyPath:options:context:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_akk2cd( + object$.ref.pointer, + _sel_addObserver_forKeyPath_options_context_, + observer.ref.pointer, + forKeyPath.ref.pointer, + options, + context, + ); + } + + /// removeObserver:forKeyPath: + void removeObserver( + objc.NSObject observer, { + required objc.NSString forKeyPath, + }) { + objc.checkOsVersionInternal( + 'NSObject.removeObserver:forKeyPath:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_removeObserver_forKeyPath_, + observer.ref.pointer, + forKeyPath.ref.pointer, + ); + } + + /// removeObserver:forKeyPath:context: + void removeObserver$1( + objc.NSObject observer, { + required objc.NSString forKeyPath, + required ffi.Pointer context, + }) { + objc.checkOsVersionInternal( + 'NSObject.removeObserver:forKeyPath:context:', + iOS: (false, (5, 0, 0)), + macOS: (false, (10, 7, 0)), + ); + _objc_msgSend_1jed5jl( + object$.ref.pointer, + _sel_removeObserver_forKeyPath_context_, + observer.ref.pointer, + forKeyPath.ref.pointer, + context, + ); + } +} + +late final _sel_willChangeValueForKey_ = objc.registerName( + "willChangeValueForKey:", +); +late final _sel_didChangeValueForKey_ = objc.registerName( + "didChangeValueForKey:", +); +late final _sel_willChange_valuesAtIndexes_forKey_ = objc.registerName( + "willChange:valuesAtIndexes:forKey:", +); +final _objc_msgSend_1diehjo = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_didChange_valuesAtIndexes_forKey_ = objc.registerName( + "didChange:valuesAtIndexes:forKey:", +); +late final _sel_willChangeValueForKey_withSetMutation_usingObjects_ = objc + .registerName("willChangeValueForKey:withSetMutation:usingObjects:"); +final _objc_msgSend_7w1jp7 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +late final _sel_didChangeValueForKey_withSetMutation_usingObjects_ = objc + .registerName("didChangeValueForKey:withSetMutation:usingObjects:"); + +/// NSKeyValueObserverNotification +extension NSKeyValueObserverNotification on objc.NSObject { + /// didChange:valuesAtIndexes:forKey: + void didChange( + objc.NSKeyValueChange changeKind, { + required objc.NSIndexSet valuesAtIndexes, + required objc.NSString forKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.didChange:valuesAtIndexes:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1diehjo( + object$.ref.pointer, + _sel_didChange_valuesAtIndexes_forKey_, + changeKind.value, + valuesAtIndexes.ref.pointer, + forKey.ref.pointer, + ); + } + + /// didChangeValueForKey: + void didChangeValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.didChangeValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_didChangeValueForKey_, + key.ref.pointer, + ); + } + + /// didChangeValueForKey:withSetMutation:usingObjects: + void didChangeValueForKey$1( + objc.NSString key, { + required objc.NSKeyValueSetMutationKind withSetMutation, + required objc.NSSet usingObjects, + }) { + objc.checkOsVersionInternal( + 'NSObject.didChangeValueForKey:withSetMutation:usingObjects:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_7w1jp7( + object$.ref.pointer, + _sel_didChangeValueForKey_withSetMutation_usingObjects_, + key.ref.pointer, + withSetMutation.value, + usingObjects.ref.pointer, + ); + } + + /// willChange:valuesAtIndexes:forKey: + void willChange( + objc.NSKeyValueChange changeKind, { + required objc.NSIndexSet valuesAtIndexes, + required objc.NSString forKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.willChange:valuesAtIndexes:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1diehjo( + object$.ref.pointer, + _sel_willChange_valuesAtIndexes_forKey_, + changeKind.value, + valuesAtIndexes.ref.pointer, + forKey.ref.pointer, + ); + } + + /// willChangeValueForKey: + void willChangeValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.willChangeValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_willChangeValueForKey_, + key.ref.pointer, + ); + } + + /// willChangeValueForKey:withSetMutation:usingObjects: + void willChangeValueForKey$1( + objc.NSString key, { + required objc.NSKeyValueSetMutationKind withSetMutation, + required objc.NSSet usingObjects, + }) { + objc.checkOsVersionInternal( + 'NSObject.willChangeValueForKey:withSetMutation:usingObjects:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_7w1jp7( + object$.ref.pointer, + _sel_willChangeValueForKey_withSetMutation_usingObjects_, + key.ref.pointer, + withSetMutation.value, + usingObjects.ref.pointer, + ); + } +} + +late final _sel_keyPathsForValuesAffectingValueForKey_ = objc.registerName( + "keyPathsForValuesAffectingValueForKey:", +); +late final _sel_automaticallyNotifiesObserversForKey_ = objc.registerName( + "automaticallyNotifiesObserversForKey:", +); +late final _sel_observationInfo = objc.registerName("observationInfo"); +final _objc_msgSend_6ex6p5 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_setObservationInfo_ = objc.registerName("setObservationInfo:"); +final _objc_msgSend_ovsamd = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// NSKeyValueObservingCustomization +extension NSKeyValueObservingCustomization on objc.NSObject { + /// observationInfo + ffi.Pointer get observationInfo { + objc.checkOsVersionInternal( + 'NSObject.observationInfo', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_6ex6p5(object$.ref.pointer, _sel_observationInfo); + } + + /// setObservationInfo: + set observationInfo(ffi.Pointer value) { + objc.checkOsVersionInternal( + 'NSObject.setObservationInfo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_ovsamd(object$.ref.pointer, _sel_setObservationInfo_, value); + } + + /// automaticallyNotifiesObserversForKey: + static bool automaticallyNotifiesObserversForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.automaticallyNotifiesObserversForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + _class_NSObject, + _sel_automaticallyNotifiesObserversForKey_, + key.ref.pointer, + ); + } + + /// keyPathsForValuesAffectingValueForKey: + static objc.NSSet keyPathsForValuesAffectingValueForKey(objc.NSString key) { + objc.checkOsVersionInternal( + 'NSObject.keyPathsForValuesAffectingValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 5, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _class_NSObject, + _sel_keyPathsForValuesAffectingValueForKey_, + key.ref.pointer, + ); + return objc.NSSet.fromPointer($ret, retain: true, release: true); + } +} + +late final _sel_setKeys_triggerChangeNotificationsForDependentKey_ = objc + .registerName("setKeys:triggerChangeNotificationsForDependentKey:"); + +/// NSDeprecatedKeyValueObservingCustomization +extension NSDeprecatedKeyValueObservingCustomization on objc.NSObject { + /// setKeys:triggerChangeNotificationsForDependentKey: + static void setKeys( + objc.NSArray keys, { + required objc.NSString triggerChangeNotificationsForDependentKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.setKeys:triggerChangeNotificationsForDependentKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + _class_NSObject, + _sel_setKeys_triggerChangeNotificationsForDependentKey_, + keys.ref.pointer, + triggerChangeNotificationsForDependentKey.ref.pointer, + ); + } +} + +/// WARNING: NSKeyValueSharedObserversSnapshot is a stub. To generate bindings for this class, include +/// NSKeyValueSharedObserversSnapshot in your config's objc-interfaces list. +/// +/// NSKeyValueSharedObserversSnapshot +extension type NSKeyValueSharedObserversSnapshot._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSKeyValueSharedObserversSnapshot] that points to the same underlying object as [other]. + NSKeyValueSharedObserversSnapshot.as(objc.ObjCObject other) + : object$ = other { + objc.checkOsVersionInternal( + 'NSKeyValueSharedObserversSnapshot', + iOS: (false, (18, 0, 0)), + macOS: (false, (15, 0, 0)), + ); + } + + /// Constructs a [NSKeyValueSharedObserversSnapshot] that wraps the given raw object pointer. + NSKeyValueSharedObserversSnapshot.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'NSKeyValueSharedObserversSnapshot', + iOS: (false, (18, 0, 0)), + macOS: (false, (15, 0, 0)), + ); + } +} + +late final _sel_setSharedObservers_ = objc.registerName("setSharedObservers:"); + +/// NSKeyValueSharedObserverRegistration +extension NSKeyValueSharedObserverRegistration on objc.NSObject { + /// setSharedObservers: + void setSharedObservers(NSKeyValueSharedObserversSnapshot? sharedObservers) { + objc.checkOsVersionInternal( + 'NSObject.setSharedObservers:', + iOS: (false, (18, 0, 0)), + macOS: (false, (15, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_setSharedObservers_, + sharedObservers?.ref.pointer ?? ffi.nullptr, + ); + } +} + +/// WARNING: NSKeyedArchiver is a stub. To generate bindings for this class, include +/// NSKeyedArchiver in your config's objc-interfaces list. +/// +/// NSKeyedArchiver +extension type NSKeyedArchiver._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSCoder { + /// Constructs a [NSKeyedArchiver] that points to the same underlying object as [other]. + NSKeyedArchiver.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSKeyedArchiver] that wraps the given raw object pointer. + NSKeyedArchiver.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +late final _sel_classForKeyedArchiver = objc.registerName( + "classForKeyedArchiver", +); +late final _sel_replacementObjectForKeyedArchiver_ = objc.registerName( + "replacementObjectForKeyedArchiver:", +); +late final _sel_classFallbacksForKeyedArchiver = objc.registerName( + "classFallbacksForKeyedArchiver", +); + +/// NSKeyedArchiverObjectSubstitution +extension NSKeyedArchiverObjectSubstitution on objc.NSObject { + /// classForKeyedArchiver + objc.ObjCObject? get classForKeyedArchiver { + objc.checkOsVersionInternal( + 'NSObject.classForKeyedArchiver', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_classForKeyedArchiver, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// replacementObjectForKeyedArchiver: + objc.ObjCObject? replacementObjectForKeyedArchiver(NSKeyedArchiver archiver) { + objc.checkOsVersionInternal( + 'NSObject.replacementObjectForKeyedArchiver:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_replacementObjectForKeyedArchiver_, + archiver.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// classFallbacksForKeyedArchiver + static objc.NSArray classFallbacksForKeyedArchiver() { + objc.checkOsVersionInternal( + 'NSObject.classFallbacksForKeyedArchiver', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + _class_NSObject, + _sel_classFallbacksForKeyedArchiver, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } +} + +late final _sel_classForKeyedUnarchiver = objc.registerName( + "classForKeyedUnarchiver", +); + +/// NSKeyedUnarchiverObjectSubstitution +extension NSKeyedUnarchiverObjectSubstitution on objc.NSObject { + /// classForKeyedUnarchiver + static objc.ObjCObject classForKeyedUnarchiver() { + objc.checkOsVersionInternal( + 'NSObject.classForKeyedUnarchiver', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + _class_NSObject, + _sel_classForKeyedUnarchiver, + ); + return objc.ObjCObject($ret, retain: true, release: true); + } +} + +/// WARNING: NSThread is a stub. To generate bindings for this class, include +/// NSThread in your config's objc-interfaces list. +/// +/// NSThread +extension type NSThread._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSThread] that points to the same underlying object as [other]. + NSThread.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSThread] that wraps the given raw object pointer. + NSThread.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_ = + objc.registerName( + "performSelectorOnMainThread:withObject:waitUntilDone:modes:", + ); +final _objc_msgSend_1fdou4m = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ffi.Pointer, + ) + >(); +late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_ = objc + .registerName("performSelectorOnMainThread:withObject:waitUntilDone:"); +final _objc_msgSend_tsocn4 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ) + >(); +late final _sel_performSelector_onThread_withObject_waitUntilDone_modes_ = objc + .registerName("performSelector:onThread:withObject:waitUntilDone:modes:"); +final _objc_msgSend_1cc1buo = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ffi.Pointer, + ) + >(); +late final _sel_performSelector_onThread_withObject_waitUntilDone_ = objc + .registerName("performSelector:onThread:withObject:waitUntilDone:"); +final _objc_msgSend_1whyima = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ) + >(); +late final _sel_performSelectorInBackground_withObject_ = objc.registerName( + "performSelectorInBackground:withObject:", +); +final _objc_msgSend_1qv0eq4 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// NSThreadPerformAdditions +extension NSThreadPerformAdditions on objc.NSObject { + /// performSelector:onThread:withObject:waitUntilDone: + void performSelector( + ffi.Pointer aSelector, { + required NSThread onThread, + objc.ObjCObject? withObject, + required bool waitUntilDone, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelector:onThread:withObject:waitUntilDone:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 5, 0)), + ); + _objc_msgSend_1whyima( + object$.ref.pointer, + _sel_performSelector_onThread_withObject_waitUntilDone_, + aSelector, + onThread.ref.pointer, + withObject?.ref.pointer ?? ffi.nullptr, + waitUntilDone, + ); + } + + /// performSelector:onThread:withObject:waitUntilDone:modes: + void performSelector$1( + ffi.Pointer aSelector, { + required NSThread onThread, + objc.ObjCObject? withObject, + required bool waitUntilDone, + objc.NSArray? modes, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelector:onThread:withObject:waitUntilDone:modes:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 5, 0)), + ); + _objc_msgSend_1cc1buo( + object$.ref.pointer, + _sel_performSelector_onThread_withObject_waitUntilDone_modes_, + aSelector, + onThread.ref.pointer, + withObject?.ref.pointer ?? ffi.nullptr, + waitUntilDone, + modes?.ref.pointer ?? ffi.nullptr, + ); + } + + /// performSelectorInBackground:withObject: + void performSelectorInBackground( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelectorInBackground:withObject:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 5, 0)), + ); + _objc_msgSend_1qv0eq4( + object$.ref.pointer, + _sel_performSelectorInBackground_withObject_, + aSelector, + withObject?.ref.pointer ?? ffi.nullptr, + ); + } + + /// performSelectorOnMainThread:withObject:waitUntilDone: + void performSelectorOnMainThread( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required bool waitUntilDone, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelectorOnMainThread:withObject:waitUntilDone:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_tsocn4( + object$.ref.pointer, + _sel_performSelectorOnMainThread_withObject_waitUntilDone_, + aSelector, + withObject?.ref.pointer ?? ffi.nullptr, + waitUntilDone, + ); + } + + /// performSelectorOnMainThread:withObject:waitUntilDone:modes: + void performSelectorOnMainThread$1( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required bool waitUntilDone, + objc.NSArray? modes, + }) { + objc.checkOsVersionInternal( + 'NSObject.performSelectorOnMainThread:withObject:waitUntilDone:modes:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1fdou4m( + object$.ref.pointer, + _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_, + aSelector, + withObject?.ref.pointer ?? ffi.nullptr, + waitUntilDone, + modes?.ref.pointer ?? ffi.nullptr, + ); + } +} + +/// WARNING: NSArchiver is a stub. To generate bindings for this class, include +/// NSArchiver in your config's objc-interfaces list. +/// +/// NSArchiver +extension type NSArchiver._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSCoder { + /// Constructs a [NSArchiver] that points to the same underlying object as [other]. + NSArchiver.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'NSArchiver', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + } + + /// Constructs a [NSArchiver] that wraps the given raw object pointer. + NSArchiver.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'NSArchiver', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + } +} + +late final _sel_classForArchiver = objc.registerName("classForArchiver"); +late final _sel_replacementObjectForArchiver_ = objc.registerName( + "replacementObjectForArchiver:", +); + +/// NSArchiverCallback +extension NSArchiverCallback on objc.NSObject { + /// classForArchiver + objc.ObjCObject? get classForArchiver { + objc.checkOsVersionInternal( + 'NSObject.classForArchiver', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_classForArchiver, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// replacementObjectForArchiver: + objc.ObjCObject? replacementObjectForArchiver(NSArchiver archiver) { + objc.checkOsVersionInternal( + 'NSObject.replacementObjectForArchiver:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_replacementObjectForArchiver_, + archiver.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } +} + +/// WARNING: NSPortCoder is a stub. To generate bindings for this class, include +/// NSPortCoder in your config's objc-interfaces list. +/// +/// NSPortCoder +extension type NSPortCoder._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSCoder { + /// Constructs a [NSPortCoder] that points to the same underlying object as [other]. + NSPortCoder.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'NSPortCoder', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + } + + /// Constructs a [NSPortCoder] that wraps the given raw object pointer. + NSPortCoder.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'NSPortCoder', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + } +} + +late final _sel_classForPortCoder = objc.registerName("classForPortCoder"); +late final _sel_replacementObjectForPortCoder_ = objc.registerName( + "replacementObjectForPortCoder:", +); + +/// NSDistributedObjects +extension NSDistributedObjects on objc.NSObject { + /// classForPortCoder + objc.ObjCObject get classForPortCoder { + objc.checkOsVersionInternal( + 'NSObject.classForPortCoder', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_classForPortCoder, + ); + return objc.ObjCObject($ret, retain: true, release: true); + } + + /// replacementObjectForPortCoder: + objc.ObjCObject? replacementObjectForPortCoder(NSPortCoder coder) { + objc.checkOsVersionInternal( + 'NSObject.replacementObjectForPortCoder:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_replacementObjectForPortCoder_, + coder.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } +} + +/// WARNING: NSClassDescription is a stub. To generate bindings for this class, include +/// NSClassDescription in your config's objc-interfaces list. +/// +/// NSClassDescription +extension type NSClassDescription._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSClassDescription] that points to the same underlying object as [other]. + NSClassDescription.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSClassDescription] that wraps the given raw object pointer. + NSClassDescription.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +late final _sel_classDescription = objc.registerName("classDescription"); +late final _sel_attributeKeys = objc.registerName("attributeKeys"); +late final _sel_toOneRelationshipKeys = objc.registerName( + "toOneRelationshipKeys", +); +late final _sel_toManyRelationshipKeys = objc.registerName( + "toManyRelationshipKeys", +); +late final _sel_inverseForRelationshipKey_ = objc.registerName( + "inverseForRelationshipKey:", +); + +/// NSClassDescriptionPrimitives +extension NSClassDescriptionPrimitives on objc.NSObject { + /// attributeKeys + objc.NSArray get attributeKeys { + objc.checkOsVersionInternal( + 'NSObject.attributeKeys', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_attributeKeys); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } + + /// classDescription + NSClassDescription get classDescription { + objc.checkOsVersionInternal( + 'NSObject.classDescription', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_classDescription, + ); + return NSClassDescription.fromPointer($ret, retain: true, release: true); + } + + /// inverseForRelationshipKey: + objc.NSString? inverseForRelationshipKey(objc.NSString relationshipKey) { + objc.checkOsVersionInternal( + 'NSObject.inverseForRelationshipKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_inverseForRelationshipKey_, + relationshipKey.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.NSString.fromPointer($ret, retain: true, release: true); + } + + /// toManyRelationshipKeys + objc.NSArray get toManyRelationshipKeys { + objc.checkOsVersionInternal( + 'NSObject.toManyRelationshipKeys', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_toManyRelationshipKeys, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } + + /// toOneRelationshipKeys + objc.NSArray get toOneRelationshipKeys { + objc.checkOsVersionInternal( + 'NSObject.toOneRelationshipKeys', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_toOneRelationshipKeys, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } +} + +/// WARNING: NSScriptObjectSpecifier is a stub. To generate bindings for this class, include +/// NSScriptObjectSpecifier in your config's objc-interfaces list. +/// +/// NSScriptObjectSpecifier +extension type NSScriptObjectSpecifier._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCoding { + /// Constructs a [NSScriptObjectSpecifier] that points to the same underlying object as [other]. + NSScriptObjectSpecifier.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSScriptObjectSpecifier] that wraps the given raw object pointer. + NSScriptObjectSpecifier.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +late final _sel_scriptingValueForSpecifier_ = objc.registerName( + "scriptingValueForSpecifier:", +); +late final _sel_scriptingProperties = objc.registerName("scriptingProperties"); +late final _sel_setScriptingProperties_ = objc.registerName( + "setScriptingProperties:", +); +late final _sel_copyScriptingValue_forKey_withProperties_ = objc.registerName( + "copyScriptingValue:forKey:withProperties:", +); +final _objc_msgSend_11spmsz = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_ = + objc.registerName( + "newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:", + ); +final _objc_msgSend_s92gih = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); + +/// NSScripting +extension NSScripting on objc.NSObject { + /// copyScriptingValue:forKey:withProperties: + objc.ObjCObject? copyScriptingValue( + objc.ObjCObject value, { + required objc.NSString forKey, + required objc.NSDictionary withProperties, + }) { + objc.checkOsVersionInternal( + 'NSObject.copyScriptingValue:forKey:withProperties:', + iOS: (true, null), + macOS: (false, (10, 5, 0)), + ); + final $ret = _objc_msgSend_11spmsz( + object$.ref.pointer, + _sel_copyScriptingValue_forKey_withProperties_, + value.ref.pointer, + forKey.ref.pointer, + withProperties.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: false, release: true); + } + + /// newScriptingObjectOfClass:forValueForKey:withContentsValue:properties: + objc.ObjCObject? newScriptingObjectOfClass( + objc.ObjCObject objectClass, { + required objc.NSString forValueForKey, + objc.ObjCObject? withContentsValue, + required objc.NSDictionary properties, + }) { + objc.checkOsVersionInternal( + 'NSObject.newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:', + iOS: (true, null), + macOS: (false, (10, 5, 0)), + ); + final $ret = _objc_msgSend_s92gih( + object$.ref.pointer, + _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_, + objectClass.ref.pointer, + forValueForKey.ref.pointer, + withContentsValue?.ref.pointer ?? ffi.nullptr, + properties.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: false, release: true); + } + + /// scriptingProperties + objc.NSDictionary? get scriptingProperties { + objc.checkOsVersionInternal( + 'NSObject.scriptingProperties', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_scriptingProperties, + ); + return $ret.address == 0 + ? null + : objc.NSDictionary.fromPointer($ret, retain: true, release: true); + } + + /// scriptingValueForSpecifier: + objc.ObjCObject? scriptingValueForSpecifier( + NSScriptObjectSpecifier objectSpecifier, + ) { + objc.checkOsVersionInternal( + 'NSObject.scriptingValueForSpecifier:', + iOS: (true, null), + macOS: (false, (10, 5, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_scriptingValueForSpecifier_, + objectSpecifier.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// setScriptingProperties: + set scriptingProperties(objc.NSDictionary? value) { + objc.checkOsVersionInternal( + 'NSObject.setScriptingProperties:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_xtuoz7( + object$.ref.pointer, + _sel_setScriptingProperties_, + value?.ref.pointer ?? ffi.nullptr, + ); + } +} + +late final _sel_classCode = objc.registerName("classCode"); +final _objc_msgSend_3pyzne = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.UnsignedInt Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_className = objc.registerName("className"); + +/// NSScriptClassDescription +extension NSScriptClassDescription on objc.NSObject { + /// classCode + int get classCode { + objc.checkOsVersionInternal( + 'NSObject.classCode', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_3pyzne(object$.ref.pointer, _sel_classCode); + } + + /// className + objc.NSString get className { + objc.checkOsVersionInternal( + 'NSObject.className', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_className); + return objc.NSString.fromPointer($ret, retain: true, release: true); + } +} + +late final _sel_valueAtIndex_inPropertyWithKey_ = objc.registerName( + "valueAtIndex:inPropertyWithKey:", +); +final _objc_msgSend_vbc8p4 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( ffi.Pointer, ffi.Pointer, + ffi.UnsignedLong, ffi.Pointer, ) > >() .asFunction< - bool Function( + ffi.Pointer Function( ffi.Pointer, ffi.Pointer, + int, ffi.Pointer, ) >(); -late final _sel_defaultManager = objc.registerName("defaultManager"); -final _objc_msgSend_151sglz = objc.msgSendPointer +late final _sel_valueWithName_inPropertyWithKey_ = objc.registerName( + "valueWithName:inPropertyWithKey:", +); +final _objc_msgSend_15qeuct = objc.msgSendPointer .cast< ffi.NativeFunction< ffi.Pointer Function( ffi.Pointer, ffi.Pointer, + ffi.Pointer, + ffi.Pointer, ) > >() @@ -99,125 +2732,571 @@ final _objc_msgSend_151sglz = objc.msgSendPointer ffi.Pointer Function( ffi.Pointer, ffi.Pointer, + ffi.Pointer, + ffi.Pointer, ) >(); -late final _sel_isReadableFileAtPath_ = objc.registerName( - "isReadableFileAtPath:", +late final _sel_valueWithUniqueID_inPropertyWithKey_ = objc.registerName( + "valueWithUniqueID:inPropertyWithKey:", +); +late final _sel_insertValue_atIndex_inPropertyWithKey_ = objc.registerName( + "insertValue:atIndex:inPropertyWithKey:", +); +final _objc_msgSend_10nfbmq = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +late final _sel_removeValueAtIndex_fromPropertyWithKey_ = objc.registerName( + "removeValueAtIndex:fromPropertyWithKey:", +); +final _objc_msgSend_1gypgok = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +late final _sel_replaceValueAtIndex_inPropertyWithKey_withValue_ = objc + .registerName("replaceValueAtIndex:inPropertyWithKey:withValue:"); +final _objc_msgSend_rutu22 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ) + >(); +late final _sel_insertValue_inPropertyWithKey_ = objc.registerName( + "insertValue:inPropertyWithKey:", +); +late final _sel_coerceValue_forKey_ = objc.registerName("coerceValue:forKey:"); + +/// NSScriptKeyValueCoding +extension NSScriptKeyValueCoding on objc.NSObject { + /// coerceValue:forKey: + objc.ObjCObject? coerceValue( + objc.ObjCObject? value, { + required objc.NSString forKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.coerceValue:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + object$.ref.pointer, + _sel_coerceValue_forKey_, + value?.ref.pointer ?? ffi.nullptr, + forKey.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// insertValue:atIndex:inPropertyWithKey: + void insertValue( + objc.ObjCObject value, { + required int atIndex, + required objc.NSString inPropertyWithKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.insertValue:atIndex:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_10nfbmq( + object$.ref.pointer, + _sel_insertValue_atIndex_inPropertyWithKey_, + value.ref.pointer, + atIndex, + inPropertyWithKey.ref.pointer, + ); + } + + /// insertValue:inPropertyWithKey: + void insertValue$1( + objc.ObjCObject value, { + required objc.NSString inPropertyWithKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.insertValue:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + object$.ref.pointer, + _sel_insertValue_inPropertyWithKey_, + value.ref.pointer, + inPropertyWithKey.ref.pointer, + ); + } + + /// removeValueAtIndex:fromPropertyWithKey: + void removeValueAtIndex( + int index, { + required objc.NSString fromPropertyWithKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.removeValueAtIndex:fromPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1gypgok( + object$.ref.pointer, + _sel_removeValueAtIndex_fromPropertyWithKey_, + index, + fromPropertyWithKey.ref.pointer, + ); + } + + /// replaceValueAtIndex:inPropertyWithKey:withValue: + void replaceValueAtIndex( + int index, { + required objc.NSString inPropertyWithKey, + required objc.ObjCObject withValue, + }) { + objc.checkOsVersionInternal( + 'NSObject.replaceValueAtIndex:inPropertyWithKey:withValue:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_rutu22( + object$.ref.pointer, + _sel_replaceValueAtIndex_inPropertyWithKey_withValue_, + index, + inPropertyWithKey.ref.pointer, + withValue.ref.pointer, + ); + } + + /// valueAtIndex:inPropertyWithKey: + objc.ObjCObject? valueAtIndex( + int index, { + required objc.NSString inPropertyWithKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.valueAtIndex:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_vbc8p4( + object$.ref.pointer, + _sel_valueAtIndex_inPropertyWithKey_, + index, + inPropertyWithKey.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// valueWithName:inPropertyWithKey: + objc.ObjCObject? valueWithName( + objc.NSString name, { + required objc.NSString inPropertyWithKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.valueWithName:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + object$.ref.pointer, + _sel_valueWithName_inPropertyWithKey_, + name.ref.pointer, + inPropertyWithKey.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } + + /// valueWithUniqueID:inPropertyWithKey: + objc.ObjCObject? valueWithUniqueID( + objc.ObjCObject uniqueID, { + required objc.NSString inPropertyWithKey, + }) { + objc.checkOsVersionInternal( + 'NSObject.valueWithUniqueID:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + object$.ref.pointer, + _sel_valueWithUniqueID_inPropertyWithKey_, + uniqueID.ref.pointer, + inPropertyWithKey.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.ObjCObject($ret, retain: true, release: true); + } +} + +late final _sel_objectSpecifier = objc.registerName("objectSpecifier"); +late final _sel_indicesOfObjectsByEvaluatingObjectSpecifier_ = objc + .registerName("indicesOfObjectsByEvaluatingObjectSpecifier:"); + +/// NSScriptObjectSpecifiers +extension NSScriptObjectSpecifiers on objc.NSObject { + /// indicesOfObjectsByEvaluatingObjectSpecifier: + objc.NSArray? indicesOfObjectsByEvaluatingObjectSpecifier( + NSScriptObjectSpecifier specifier, + ) { + objc.checkOsVersionInternal( + 'NSObject.indicesOfObjectsByEvaluatingObjectSpecifier:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + object$.ref.pointer, + _sel_indicesOfObjectsByEvaluatingObjectSpecifier_, + specifier.ref.pointer, + ); + return $ret.address == 0 + ? null + : objc.NSArray.fromPointer($ret, retain: true, release: true); + } + + /// objectSpecifier + NSScriptObjectSpecifier? get objectSpecifier { + objc.checkOsVersionInternal( + 'NSObject.objectSpecifier', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz( + object$.ref.pointer, + _sel_objectSpecifier, + ); + return $ret.address == 0 + ? null + : NSScriptObjectSpecifier.fromPointer( + $ret, + retain: true, + release: true, + ); + } +} + +late final _sel_isEqualTo_ = objc.registerName("isEqualTo:"); +late final _sel_isLessThanOrEqualTo_ = objc.registerName( + "isLessThanOrEqualTo:", +); +late final _sel_isLessThan_ = objc.registerName("isLessThan:"); +late final _sel_isGreaterThanOrEqualTo_ = objc.registerName( + "isGreaterThanOrEqualTo:", +); +late final _sel_isGreaterThan_ = objc.registerName("isGreaterThan:"); +late final _sel_isNotEqualTo_ = objc.registerName("isNotEqualTo:"); +late final _sel_doesContain_ = objc.registerName("doesContain:"); +late final _sel_isLike_ = objc.registerName("isLike:"); +late final _sel_isCaseInsensitiveLike_ = objc.registerName( + "isCaseInsensitiveLike:", +); + +/// NSComparisonMethods +extension NSComparisonMethods on objc.NSObject { + /// doesContain: + bool doesContain(objc.ObjCObject object) { + objc.checkOsVersionInternal( + 'NSObject.doesContain:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_doesContain_, + object.ref.pointer, + ); + } + + /// isCaseInsensitiveLike: + bool isCaseInsensitiveLike(objc.NSString object) { + objc.checkOsVersionInternal( + 'NSObject.isCaseInsensitiveLike:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isCaseInsensitiveLike_, + object.ref.pointer, + ); + } + + /// isEqualTo: + bool isEqualTo(objc.ObjCObject? object) { + objc.checkOsVersionInternal( + 'NSObject.isEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isEqualTo_, + object?.ref.pointer ?? ffi.nullptr, + ); + } + + /// isGreaterThan: + bool isGreaterThan(objc.ObjCObject? object) { + objc.checkOsVersionInternal( + 'NSObject.isGreaterThan:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isGreaterThan_, + object?.ref.pointer ?? ffi.nullptr, + ); + } + + /// isGreaterThanOrEqualTo: + bool isGreaterThanOrEqualTo(objc.ObjCObject? object) { + objc.checkOsVersionInternal( + 'NSObject.isGreaterThanOrEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isGreaterThanOrEqualTo_, + object?.ref.pointer ?? ffi.nullptr, + ); + } + + /// isLessThan: + bool isLessThan(objc.ObjCObject? object) { + objc.checkOsVersionInternal( + 'NSObject.isLessThan:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isLessThan_, + object?.ref.pointer ?? ffi.nullptr, + ); + } + + /// isLessThanOrEqualTo: + bool isLessThanOrEqualTo(objc.ObjCObject? object) { + objc.checkOsVersionInternal( + 'NSObject.isLessThanOrEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isLessThanOrEqualTo_, + object?.ref.pointer ?? ffi.nullptr, + ); + } + + /// isLike: + bool isLike(objc.NSString object) { + objc.checkOsVersionInternal( + 'NSObject.isLike:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isLike_, + object.ref.pointer, + ); + } + + /// isNotEqualTo: + bool isNotEqualTo(objc.ObjCObject? object) { + objc.checkOsVersionInternal( + 'NSObject.isNotEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_isNotEqualTo_, + object?.ref.pointer ?? ffi.nullptr, + ); + } +} + +late final _sel_scriptingIsEqualTo_ = objc.registerName("scriptingIsEqualTo:"); +late final _sel_scriptingIsLessThanOrEqualTo_ = objc.registerName( + "scriptingIsLessThanOrEqualTo:", ); -late final _sel_homeDirectoryForCurrentUser = objc.registerName( - "homeDirectoryForCurrentUser", +late final _sel_scriptingIsLessThan_ = objc.registerName( + "scriptingIsLessThan:", ); -late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); -late final _sel_homeDirectoryForUser_ = objc.registerName( - "homeDirectoryForUser:", +late final _sel_scriptingIsGreaterThanOrEqualTo_ = objc.registerName( + "scriptingIsGreaterThanOrEqualTo:", ); -final _objc_msgSend_1sotr3r = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); +late final _sel_scriptingIsGreaterThan_ = objc.registerName( + "scriptingIsGreaterThan:", +); +late final _sel_scriptingBeginsWith_ = objc.registerName( + "scriptingBeginsWith:", +); +late final _sel_scriptingEndsWith_ = objc.registerName("scriptingEndsWith:"); +late final _sel_scriptingContains_ = objc.registerName("scriptingContains:"); -/// NSUserInformation -extension NSUserInformation on NSFileManager { - /// homeDirectoryForCurrentUser - objc.NSURL get homeDirectoryForCurrentUser { +/// NSScriptingComparisonMethods +extension NSScriptingComparisonMethods on objc.NSObject { + /// scriptingBeginsWith: + bool scriptingBeginsWith(objc.ObjCObject object) { objc.checkOsVersionInternal( - 'NSFileManager.homeDirectoryForCurrentUser', - iOS: (true, null), - macOS: (false, (10, 12, 0)), + 'NSObject.scriptingBeginsWith:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( + return _objc_msgSend_19nvye5( object$.ref.pointer, - _sel_homeDirectoryForCurrentUser, + _sel_scriptingBeginsWith_, + object.ref.pointer, ); - return objc.NSURL.fromPointer($ret, retain: true, release: true); } - /// homeDirectoryForUser: - objc.NSURL? homeDirectoryForUser(objc.NSString userName) { + /// scriptingContains: + bool scriptingContains(objc.ObjCObject object) { objc.checkOsVersionInternal( - 'NSFileManager.homeDirectoryForUser:', - iOS: (true, null), - macOS: (false, (10, 12, 0)), + 'NSObject.scriptingContains:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( + return _objc_msgSend_19nvye5( object$.ref.pointer, - _sel_homeDirectoryForUser_, - userName.ref.pointer, + _sel_scriptingContains_, + object.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.NSURL.fromPointer($ret, retain: true, release: true); } - /// temporaryDirectory - objc.NSURL get temporaryDirectory { + /// scriptingEndsWith: + bool scriptingEndsWith(objc.ObjCObject object) { objc.checkOsVersionInternal( - 'NSFileManager.temporaryDirectory', - iOS: (false, (10, 0, 0)), - macOS: (false, (10, 12, 0)), + 'NSObject.scriptingEndsWith:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( + return _objc_msgSend_19nvye5( object$.ref.pointer, - _sel_temporaryDirectory, + _sel_scriptingEndsWith_, + object.ref.pointer, ); - return objc.NSURL.fromPointer($ret, retain: true, release: true); } -} -/// NSFileManager -extension type NSFileManager._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [NSFileManager] that points to the same underlying object as [other]. - NSFileManager.as(objc.ObjCObject other) : object$ = other { - assert(isA(object$)); + /// scriptingIsEqualTo: + bool scriptingIsEqualTo(objc.ObjCObject object) { + objc.checkOsVersionInternal( + 'NSObject.scriptingIsEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_scriptingIsEqualTo_, + object.ref.pointer, + ); } - /// Constructs a [NSFileManager] that wraps the given raw object pointer. - NSFileManager.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - assert(isA(object$)); + /// scriptingIsGreaterThan: + bool scriptingIsGreaterThan(objc.ObjCObject object) { + objc.checkOsVersionInternal( + 'NSObject.scriptingIsGreaterThan:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_scriptingIsGreaterThan_, + object.ref.pointer, + ); } - /// Returns whether [obj] is an instance of [NSFileManager]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_NSFileManager, - ); + /// scriptingIsGreaterThanOrEqualTo: + bool scriptingIsGreaterThanOrEqualTo(objc.ObjCObject object) { + objc.checkOsVersionInternal( + 'NSObject.scriptingIsGreaterThanOrEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_scriptingIsGreaterThanOrEqualTo_, + object.ref.pointer, + ); + } - /// defaultManager - static NSFileManager getDefaultManager() { - final $ret = _objc_msgSend_151sglz( - _class_NSFileManager, - _sel_defaultManager, + /// scriptingIsLessThan: + bool scriptingIsLessThan(objc.ObjCObject object) { + objc.checkOsVersionInternal( + 'NSObject.scriptingIsLessThan:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5( + object$.ref.pointer, + _sel_scriptingIsLessThan_, + object.ref.pointer, ); - return NSFileManager.fromPointer($ret, retain: true, release: true); } -} -extension NSFileManager$Methods on NSFileManager { - /// isReadableFileAtPath: - bool isReadableFileAtPath(objc.NSString path) { + /// scriptingIsLessThanOrEqualTo: + bool scriptingIsLessThanOrEqualTo(objc.ObjCObject object) { + objc.checkOsVersionInternal( + 'NSObject.scriptingIsLessThanOrEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); return _objc_msgSend_19nvye5( object$.ref.pointer, - _sel_isReadableFileAtPath_, - path.ref.pointer, + _sel_scriptingIsLessThanOrEqualTo_, + object.ref.pointer, ); } } @@ -381,25 +3460,6 @@ extension type PHFetchOptions._(objc.ObjCObject object$) late final _sel_fetchAssetsWithLocalIdentifiers_options_ = objc.registerName( "fetchAssetsWithLocalIdentifiers:options:", ); -final _objc_msgSend_15qeuct = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); /// WARNING: PHContentEditingInputRequestOptions is a stub. To generate bindings for this class, include /// PHContentEditingInputRequestOptions in your config's objc-interfaces list. @@ -957,27 +4017,190 @@ extension PHAsset$Methods on PHAsset { } } +late final _sel_provideImageData_bytesPerRow_origin__size__userInfo_ = objc + .registerName("provideImageData:bytesPerRow:origin::size::userInfo:"); +final _objc_msgSend_haq63t = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + int, + int, + int, + int, + ffi.Pointer, + ) + >(); + +/// WARNING: MTLTexture is a stub. To generate bindings for this class, include +/// MTLTexture in your config's objc-protocols list. +/// +/// MTLTexture +extension type MTLTexture._(objc.ObjCProtocol object$) + implements objc.ObjCProtocol { + /// Constructs a [MTLTexture] that points to the same underlying object as [other]. + MTLTexture.as(objc.ObjCObject other) : object$ = other; + + /// Constructs a [MTLTexture] that wraps the given raw object pointer. + MTLTexture.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); +} + +/// WARNING: MTLCommandBuffer is a stub. To generate bindings for this class, include +/// MTLCommandBuffer in your config's objc-protocols list. +/// +/// MTLCommandBuffer +extension type MTLCommandBuffer._(objc.ObjCProtocol object$) + implements objc.ObjCProtocol { + /// Constructs a [MTLCommandBuffer] that points to the same underlying object as [other]. + MTLCommandBuffer.as(objc.ObjCObject other) : object$ = other; + + /// Constructs a [MTLCommandBuffer] that wraps the given raw object pointer. + MTLCommandBuffer.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); +} + +late final _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_ = + objc.registerName( + "provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:", + ); +final _objc_msgSend_1jjfka7 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + int, + int, + int, + ffi.Pointer, + ) + >(); + +/// CIImageProvider +extension CIImageProvider on objc.NSObject { + /// provideImageData:bytesPerRow:origin::size::userInfo: + void provideImageData( + ffi.Pointer data, { + required int bytesPerRow, + required int origin, + required int unnamed, + required int size, + required int unnamed$1, + objc.ObjCObject? userInfo, + }) { + objc.checkOsVersionInternal( + 'NSObject.provideImageData:bytesPerRow:origin::size::userInfo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_haq63t( + object$.ref.pointer, + _sel_provideImageData_bytesPerRow_origin__size__userInfo_, + data, + bytesPerRow, + origin, + unnamed, + size, + unnamed$1, + userInfo?.ref.pointer ?? ffi.nullptr, + ); + } + + /// provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo: + void provideImageToMTLTexture( + MTLTexture texture, { + required MTLCommandBuffer commandBuffer, + required int originx, + required int originy, + required int width, + required int height, + objc.ObjCObject? userInfo, + }) { + objc.checkOsVersionInternal( + 'NSObject.provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:', + macOS: (false, (26, 0, 0)), + ); + _objc_msgSend_1jjfka7( + object$.ref.pointer, + _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_, + texture.ref.pointer, + commandBuffer.ref.pointer, + originx, + originy, + width, + height, + userInfo?.ref.pointer ?? ffi.nullptr, + ); + } +} + late final _class_PHImageRequestOptions = objc.getClass( "PHImageRequestOptions", ); -late final _sel_isNetworkAccessAllowed = objc.registerName( - "isNetworkAccessAllowed", +late final _sel_setNetworkAccessAllowed_ = objc.registerName( + "setNetworkAccessAllowed:", ); -final _objc_msgSend_91o635 = objc.msgSendPointer +final _objc_msgSend_1s56lr9 = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.Bool Function( + ffi.Void Function( ffi.Pointer, ffi.Pointer, + ffi.Bool, ) > >() .asFunction< - bool Function( + void Function( ffi.Pointer, ffi.Pointer, + bool, ) >(); +typedef instancetype = ffi.Pointer; +typedef Dartinstancetype = objc.ObjCObject; +late final _sel_new = objc.registerName("new"); /// PHImageRequestOptions extension type PHImageRequestOptions._(objc.ObjCObject object$) @@ -1012,19 +4235,33 @@ extension type PHImageRequestOptions._(objc.ObjCObject object$) _sel_isKindOfClass_, _class_PHImageRequestOptions, ); + + /// new + static PHImageRequestOptions new$() { + final $ret = _objc_msgSend_151sglz(_class_PHImageRequestOptions, _sel_new); + return PHImageRequestOptions.fromPointer( + $ret, + retain: false, + release: true, + ); + } + + /// Returns a new instance of PHImageRequestOptions constructed with the default `new` method. + PHImageRequestOptions() : this.as(new$().object$); } extension PHImageRequestOptions$Methods on PHImageRequestOptions { - /// isNetworkAccessAllowed - bool get isNetworkAccessAllowed { + /// setNetworkAccessAllowed: + set isNetworkAccessAllowed(bool value) { objc.checkOsVersionInternal( - 'PHImageRequestOptions.isNetworkAccessAllowed', + 'PHImageRequestOptions.setNetworkAccessAllowed:', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - return _objc_msgSend_91o635( + _objc_msgSend_1s56lr9( object$.ref.pointer, - _sel_isNetworkAccessAllowed, + _sel_setNetworkAccessAllowed_, + value, ); } } diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index fede8663a5e1..6f3619db7515 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -29,6 +29,7 @@ void main() { include: (Declaration declaration) { return { 'NSFileManager', + 'NSObject', 'PHAsset', 'PHAssetResource', 'PHAssetResourceManager', @@ -38,6 +39,9 @@ void main() { }.contains(declaration.originalName); }, includeMember: (Declaration declaration, String member) { + if (declaration.originalName == 'PHImageRequestOptions') { + print('Apple: $member'); + } final String interfaceName = declaration.originalName; final signature = member; return switch (interfaceName) { @@ -45,6 +49,7 @@ void main() { 'defaultManager', 'isReadableFileAtPath:', }.contains(signature), + 'NSObject' => {'valueForKey:'}.contains(signature), 'PHAsset' => { 'fetchAssetsWithLocalIdentifiers:options:', 'modificationDate', @@ -63,7 +68,8 @@ void main() { 'requestImageDataAndOrientationForAsset:options:resultHandler:', }.contains(signature), 'PHImageRequestOptions' => { - 'isNetworkAccessAllowed', + 'new', + 'setNetworkAccessAllowed:', }.contains(signature), _ => false, }; From dfe9ecc9271617fa510424fc4b49f603a7d5ea35 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:04:37 -0400 Subject: [PATCH 271/398] move where the data is passed to main thread --- .../lib/src/darwin_scoped_storage_cross_file.dart | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index efc95992d3bf..05de14ef77f4 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -53,7 +53,7 @@ base class SecurityScopedDarwinScopedStorageXFileCreationParams base class PhotoKitDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { /// Constructs a [PhotoKitDarwinScopedStorageXFileCreationParams]. - PhotoKitDarwinScopedStorageXFileCreationParams({ + const PhotoKitDarwinScopedStorageXFileCreationParams({ required String localIdentifier, }) : super(uri: localIdentifier); } @@ -209,7 +209,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final ObjCObject? firstObject = resources.firstObject; if (firstObject != null) { - final PHAssetResource resource = PHAssetResource.as(firstObject); + final resource = PHAssetResource.as(firstObject); final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); print(fileSize); @@ -239,8 +239,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile NSDictionary? info, ) { if (imageData != null) { + final Uint8List bytes = _extractBytesToUint8List(imageData); runOnPlatformThread(() { - final Uint8List bytes = _extractBytesToUint8List(imageData); bytesCompleter.complete(bytes); }); } @@ -266,9 +266,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } @override - Future canRead() { - throw UnsupportedError(''); - } + Future canRead() => exists(); @override Future exists() async => _tryGetAsset(identifier: params.uri) != null; @@ -280,7 +278,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final ObjCObject? firstObject = resources.firstObject; if (firstObject != null) { - final PHAssetResource resource = PHAssetResource.as(firstObject); + final resource = PHAssetResource.as(firstObject); return resource.originalFilename.toDartString(); } } From abb39e2e7116825707c48118639f1422e5b9e392 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:25:05 -0400 Subject: [PATCH 272/398] fix library name maybe --- .../cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index 8324bdd9da47..b0eca993685f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -16,7 +16,7 @@ base class CrossFileDarwin extends CrossFileIO { static void registerWith() { CrossFilePlatform.instance = CrossFileDarwin(); ffi.DynamicLibrary.open( - '/System/Library/Frameworks/Photos.framework/Versions/Current/Photos', + '/System/Library/Frameworks/Photos.framework/Photos', ); } From 183844d568d6350f951404b17ee8056fffcfbb43 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 2 Jun 2026 17:22:55 -0400 Subject: [PATCH 273/398] support objc --- .../darwin/cross_file_darwin.podspec | 2 +- .../darwin/cross_file_darwin/Package.swift | 22 +++++++++++---- .../cross_file_darwin_objc/ffi_bindings.g.m} | 12 ++++---- .../include/placeholder.txt | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 4 +++ .../lib/src/ffi_bindings.g.dart | 28 +++++++++---------- .../cross_file_darwin/tool/ffigen.dart | 5 ++-- 7 files changed, 44 insertions(+), 30 deletions(-) rename packages/cross_file/cross_file_darwin/{lib/src/ffi_bindings.g.dart.m => darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m} (93%) create mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/include/placeholder.txt diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec index 2b40a208f48a..5d977fb76633 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin.podspec @@ -14,7 +14,7 @@ Downloaded by pub (not CocoaPods). s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_darwin' } s.documentation_url = 'https://pub.dev/packages/cross_file' - s.source_files = 'cross_file_darwin/Sources/cross_file_darwin/**/*.swift' + s.source_files = 'cross_file_darwin/Sources/**/*.{m,swift}' s.ios.dependency 'Flutter' s.osx.dependency 'FlutterMacOS' s.ios.deployment_target = '13.0' diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift index 977be8ef52db..8ce7b95081f6 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift @@ -9,8 +9,8 @@ import PackageDescription let package = Package( name: "cross_file_darwin", platforms: [ - .iOS("13.0"), - .macOS("10.15"), + .iOS(.v13), + .macOS(.v10_15), ], products: [ .library(name: "cross-file-darwin", targets: ["cross_file_darwin"]) @@ -18,11 +18,21 @@ let package = Package( dependencies: [], targets: [ .target( - name: "cross_file_darwin", + name: "cross_file_darwin", + dependencies: [ + "cross_file_darwin_objc" + ], + resources: [ + .process("Resources") + ] + ), + .target( + name: "cross_file_darwin_objc", dependencies: [], - resources: [ - .process("Resources") - ] + sources: [ + "ffi_bindings.g.m", + ], + publicHeadersPath: "include", ) ] ) diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m similarity index 93% rename from packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index 9a0ff00dea39..8cc5eb341fa2 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -51,7 +51,7 @@ typedef void (^_ListenerTrampoline)(id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _FoundationFFI_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { +_ListenerTrampoline _NativeLibrary_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1) { objc_retainBlock(block); block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); @@ -60,7 +60,7 @@ _ListenerTrampoline _FoundationFFI_wrapListenerBlock_pfv6jd(_ListenerTrampoline typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _FoundationFFI_wrapBlockingBlock_pfv6jd( +_ListenerTrampoline _NativeLibrary_wrapBlockingBlock_pfv6jd( _BlockingTrampoline block, _BlockingTrampoline listenerBlock, DOBJC_Context* ctx) NS_RETURNS_RETAINED { BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1), { @@ -74,7 +74,7 @@ _ListenerTrampoline _FoundationFFI_wrapBlockingBlock_pfv6jd( typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _FoundationFFI_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { +_ListenerTrampoline_1 _NativeLibrary_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { objc_retainBlock(block); block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); @@ -83,7 +83,7 @@ _ListenerTrampoline_1 _FoundationFFI_wrapListenerBlock_10c3wkj(_ListenerTrampoli typedef void (^_BlockingTrampoline_1)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _FoundationFFI_wrapBlockingBlock_10c3wkj( +_ListenerTrampoline_1 _NativeLibrary_wrapBlockingBlock_10c3wkj( _BlockingTrampoline_1 block, _BlockingTrampoline_1 listenerBlock, DOBJC_Context* ctx) NS_RETURNS_RETAINED { BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { @@ -97,7 +97,7 @@ _ListenerTrampoline_1 _FoundationFFI_wrapBlockingBlock_10c3wkj( typedef void (^_ListenerTrampoline_2)(id arg0); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _FoundationFFI_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { +_ListenerTrampoline_2 _NativeLibrary_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { return ^void(id arg0) { objc_retainBlock(block); block((__bridge id)(__bridge_retained void*)(arg0)); @@ -106,7 +106,7 @@ _ListenerTrampoline_2 _FoundationFFI_wrapListenerBlock_xtuoz7(_ListenerTrampolin typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _FoundationFFI_wrapBlockingBlock_xtuoz7( +_ListenerTrampoline_2 _NativeLibrary_wrapBlockingBlock_xtuoz7( _BlockingTrampoline_2 block, _BlockingTrampoline_2 listenerBlock, DOBJC_Context* ctx) NS_RETURNS_RETAINED { BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0), { diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/include/placeholder.txt b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/include/placeholder.txt new file mode 100644 index 000000000000..fa4ece6e34e6 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/include/placeholder.txt @@ -0,0 +1 @@ +Swift package manager requires an include folder for headers. \ No newline at end of file diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index d24f2c2f5f5e..a6a54c29f2bd 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -59,6 +59,8 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../darwin/cross_file_darwin; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -91,6 +93,8 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* cross_file_darwin */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 6d33ecf03494..3a3c9427e83f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -10,7 +10,7 @@ import 'package:ffi/ffi.dart' as pkg_ffi; ffi.Pointer Function(ffi.Pointer) >(isLeaf: true) external ffi.Pointer -_FoundationFFI_wrapListenerBlock_pfv6jd(ffi.Pointer block); +_NativeLibrary_wrapListenerBlock_pfv6jd(ffi.Pointer block); @ffi.Native< ffi.Pointer Function( @@ -20,7 +20,7 @@ _FoundationFFI_wrapListenerBlock_pfv6jd(ffi.Pointer block); ) >(isLeaf: true) external ffi.Pointer -_FoundationFFI_wrapBlockingBlock_pfv6jd( +_NativeLibrary_wrapBlockingBlock_pfv6jd( ffi.Pointer block, ffi.Pointer listnerBlock, ffi.Pointer context, @@ -30,7 +30,7 @@ _FoundationFFI_wrapBlockingBlock_pfv6jd( ffi.Pointer Function(ffi.Pointer) >(isLeaf: true) external ffi.Pointer -_FoundationFFI_wrapListenerBlock_10c3wkj(ffi.Pointer block); +_NativeLibrary_wrapListenerBlock_10c3wkj(ffi.Pointer block); @ffi.Native< ffi.Pointer Function( @@ -40,7 +40,7 @@ _FoundationFFI_wrapListenerBlock_10c3wkj(ffi.Pointer block); ) >(isLeaf: true) external ffi.Pointer -_FoundationFFI_wrapBlockingBlock_10c3wkj( +_NativeLibrary_wrapBlockingBlock_10c3wkj( ffi.Pointer block, ffi.Pointer listnerBlock, ffi.Pointer context, @@ -50,7 +50,7 @@ _FoundationFFI_wrapBlockingBlock_10c3wkj( ffi.Pointer Function(ffi.Pointer) >(isLeaf: true) external ffi.Pointer -_FoundationFFI_wrapListenerBlock_xtuoz7(ffi.Pointer block); +_NativeLibrary_wrapListenerBlock_xtuoz7(ffi.Pointer block); @ffi.Native< ffi.Pointer Function( @@ -60,7 +60,7 @@ _FoundationFFI_wrapListenerBlock_xtuoz7(ffi.Pointer block); ) >(isLeaf: true) external ffi.Pointer -_FoundationFFI_wrapBlockingBlock_xtuoz7( +_NativeLibrary_wrapBlockingBlock_xtuoz7( ffi.Pointer block, ffi.Pointer listnerBlock, ffi.Pointer context, @@ -3634,7 +3634,7 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapListenerBlock_pfv6jd(raw); + final wrapper = _NativeLibrary_wrapListenerBlock_pfv6jd(raw); objc.objectRelease(raw.cast()); return objc.ObjCBlock< ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) @@ -3692,7 +3692,7 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapBlockingBlock_pfv6jd( + final wrapper = _NativeLibrary_wrapBlockingBlock_pfv6jd( raw, rawListener, objc.objCContext, @@ -4443,7 +4443,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapListenerBlock_10c3wkj(raw); + final wrapper = _NativeLibrary_wrapListenerBlock_10c3wkj(raw); objc.objectRelease(raw.cast()); return objc.ObjCBlock< ffi.Void Function( @@ -4525,7 +4525,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapBlockingBlock_10c3wkj( + final wrapper = _NativeLibrary_wrapBlockingBlock_10c3wkj( raw, rawListener, objc.objCContext, @@ -5036,7 +5036,7 @@ abstract final class ObjCBlock_ffiVoid_NSData { fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapListenerBlock_xtuoz7(raw); + final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw); objc.objectRelease(raw.cast()); return objc.ObjCBlock( wrapper, @@ -5071,7 +5071,7 @@ abstract final class ObjCBlock_ffiVoid_NSData { fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapBlockingBlock_xtuoz7( + final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7( raw, rawListener, objc.objCContext, @@ -5287,7 +5287,7 @@ abstract final class ObjCBlock_ffiVoid_NSError { ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapListenerBlock_xtuoz7(raw); + final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw); objc.objectRelease(raw.cast()); return objc.ObjCBlock( wrapper, @@ -5328,7 +5328,7 @@ abstract final class ObjCBlock_ffiVoid_NSError { ), keepIsolateAlive, ); - final wrapper = _FoundationFFI_wrapBlockingBlock_xtuoz7( + final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7( raw, rawListener, objc.objCContext, diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 6f3619db7515..15202f47f0f4 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -11,9 +11,8 @@ void main() { FfiGenerator( output: Output( dartFile: packageRoot.resolve('lib/src/ffi_bindings.g.dart'), - style: const DynamicLibraryBindings( - wrapperName: 'FoundationFFI', - wrapperDocComment: 'Bindings for Foundation and Photos Library.', + objectiveCFile: packageRoot.resolve( + 'darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m', ), ), headers: Headers( From b36b01a76afed11e1a853a619ba5575b30805ecc Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 12:54:20 -0400 Subject: [PATCH 274/398] formatting and maybe implement length --- .../src/darwin_scoped_storage_cross_file.dart | 67 ++++++------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 05de14ef77f4..b2cc74f135ba 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -25,17 +25,13 @@ sealed class DarwinScopedStorageXFileCreationParams /// Constructs a [DarwinScopedStorageXFileCreationParams] with a security /// scoped uri. - factory DarwinScopedStorageXFileCreationParams.securityScoped({ - required String uri, - }) => SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri); + factory DarwinScopedStorageXFileCreationParams.securityScoped({required String uri}) => + SecurityScopedDarwinScopedStorageXFileCreationParams(uri: uri); /// Constructs a [DarwinScopedStorageXFileCreationParams] with an asset /// identifier from the Photos Library. - factory DarwinScopedStorageXFileCreationParams.photoKit({ - required String localIdentifier, - }) => PhotoKitDarwinScopedStorageXFileCreationParams( - localIdentifier: localIdentifier, - ); + factory DarwinScopedStorageXFileCreationParams.photoKit({required String localIdentifier}) => + PhotoKitDarwinScopedStorageXFileCreationParams(localIdentifier: localIdentifier); } /// Creation parameters for [SecurityScopedDarwinScopedStorageXFile]. @@ -43,9 +39,7 @@ sealed class DarwinScopedStorageXFileCreationParams base class SecurityScopedDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { /// Constructs a [SecurityScopedDarwinScopedStorageXFileCreationParams]. - const SecurityScopedDarwinScopedStorageXFileCreationParams({ - required super.uri, - }); + const SecurityScopedDarwinScopedStorageXFileCreationParams({required super.uri}); } /// Creation parameters for [PhotoKitDarwinScopedStorageXFile]. @@ -53,19 +47,15 @@ base class SecurityScopedDarwinScopedStorageXFileCreationParams base class PhotoKitDarwinScopedStorageXFileCreationParams extends DarwinScopedStorageXFileCreationParams { /// Constructs a [PhotoKitDarwinScopedStorageXFileCreationParams]. - const PhotoKitDarwinScopedStorageXFileCreationParams({ - required String localIdentifier, - }) : super(uri: localIdentifier); + const PhotoKitDarwinScopedStorageXFileCreationParams({required String localIdentifier}) + : super(uri: localIdentifier); } /// Base implementation of [PlatformScopedStorageXFile] for iOS and macOS. sealed class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { - factory DarwinScopedStorageXFile( - PlatformScopedStorageXFileCreationParams params, - ) { + factory DarwinScopedStorageXFile(PlatformScopedStorageXFileCreationParams params) { return switch (params) { - final SecurityScopedDarwinScopedStorageXFileCreationParams - securityScopedParams => + final SecurityScopedDarwinScopedStorageXFileCreationParams securityScopedParams => SecurityScopedDarwinScopedStorageXFile(securityScopedParams), final PhotoKitDarwinScopedStorageXFileCreationParams photoKitParams => PhotoKitDarwinScopedStorageXFile(photoKitParams), @@ -79,8 +69,7 @@ sealed class DarwinScopedStorageXFile extends PlatformScopedStorageXFile { /// Implementation of [DarwinScopedStorageXFile] for interacting with a /// security-scoped URL. -base class SecurityScopedDarwinScopedStorageXFile - extends DarwinScopedStorageXFile +base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFile with SecurityScopedDarwinScopedStorageXFileExtension { /// Constructs a [SecurityScopedDarwinScopedStorageXFile]. SecurityScopedDarwinScopedStorageXFile(super.params) : super._() { @@ -103,9 +92,7 @@ base class SecurityScopedDarwinScopedStorageXFile late final SecurityScopedDarwinScopedStorageXFileCreationParams params = super.params is SecurityScopedDarwinScopedStorageXFileCreationParams ? super.params as SecurityScopedDarwinScopedStorageXFileCreationParams - : SecurityScopedDarwinScopedStorageXFileCreationParams( - uri: super.params.uri, - ); + : SecurityScopedDarwinScopedStorageXFileCreationParams(uri: super.params.uri); @override SecurityScopedDarwinScopedStorageXFileExtension? get extension => this; @@ -122,22 +109,20 @@ base class SecurityScopedDarwinScopedStorageXFile @override Future length() async { try { - return _file.length(); + return _file.lengthSync(); } on FileSystemException { return null; } } @override - Stream openRead([int? start, int? end]) => - _file.openRead(start, end).cast(); + Stream openRead([int? start, int? end]) => _file.openRead(start, end).cast(); @override Future readAsBytes() => _file.readAsBytes(); @override - Future readAsString({Encoding encoding = utf8}) => - _file.readAsString(encoding: encoding); + Future readAsString({Encoding encoding = utf8}) => _file.readAsString(encoding: encoding); @override Future canRead() async { @@ -181,9 +166,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile late final PhotoKitDarwinScopedStorageXFileCreationParams params = super.params is PhotoKitDarwinScopedStorageXFileCreationParams ? super.params as PhotoKitDarwinScopedStorageXFileCreationParams - : PhotoKitDarwinScopedStorageXFileCreationParams( - localIdentifier: super.params.uri, - ); + : PhotoKitDarwinScopedStorageXFileCreationParams(localIdentifier: super.params.uri); @override PhotoKitDarwinScopedStorageXFileExtension? get extension => this; @@ -193,9 +176,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { final NSDate? date = asset.modificationDate; if (date != null) { - DateTime.fromMillisecondsSinceEpoch( - (date.timeIntervalSince1970 * 1000).round(), - ); + DateTime.fromMillisecondsSinceEpoch((date.timeIntervalSince1970 * 1000).round()); } } @@ -211,9 +192,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile if (firstObject != null) { final resource = PHAssetResource.as(firstObject); final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); - print(fileSize); - - return null; + return fileSize?.ref.pointer.cast().value; } } @@ -221,8 +200,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } @override - Stream openRead([int? start, int? end]) => - throw UnsupportedError(''); + Stream openRead([int? start, int? end]) => throw UnsupportedError(''); @override Future readAsBytes() { @@ -299,14 +277,12 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } Uint8List _extractBytesToUint8List(NSData data) { - int length = data.length; - - if (length == 0) { + if (data.length == 0) { return Uint8List(0); } final Pointer uint8Pointer = data.bytes.cast(); - final Uint8List byteView = uint8Pointer.asTypedList(length); + final Uint8List byteView = uint8Pointer.asTypedList(data.length); return Uint8List.fromList(byteView); } } @@ -318,5 +294,4 @@ mixin SecurityScopedDarwinScopedStorageXFileExtension /// Provides platform specific features for /// [PhotoKitDarwinScopedStorageXFile]. -mixin PhotoKitDarwinScopedStorageXFileExtension - implements PlatformScopedStorageXFileExtension {} +mixin PhotoKitDarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension {} From d088cae0875c3ec7071b1d55009fb8b969c7f9e2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:09:37 -0400 Subject: [PATCH 275/398] try reading from address --- .../lib/src/darwin_scoped_storage_cross_file.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index b2cc74f135ba..36562d42c8a1 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -192,7 +192,12 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile if (firstObject != null) { final resource = PHAssetResource.as(firstObject); final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); - return fileSize?.ref.pointer.cast().value; + print('here'); + if (fileSize != null) { + final Pointer pointer = Pointer.fromAddress(fileSize.ref.pointer.address); + pointer.value; + } + //return fileSize?.ref.pointer.cast().value; } } From f9edbcd8418b17e4cef8e7450880442195d6659a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:15:32 -0400 Subject: [PATCH 276/398] try unsigned long --- .../lib/src/darwin_scoped_storage_cross_file.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 36562d42c8a1..40e5ad4df6ce 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -194,10 +194,10 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); print('here'); if (fileSize != null) { - final Pointer pointer = Pointer.fromAddress(fileSize.ref.pointer.address); - pointer.value; + final Pointer pointer = Pointer.fromAddress(fileSize.ref.pointer.address); + return pointer.value; } - //return fileSize?.ref.pointer.cast().value; + //return figleSize?.ref.pointer.cast().value; } } From eaed7c4b73544aa4fc940d3e3d1ea847b7217952 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:15:59 -0400 Subject: [PATCH 277/398] add prints --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 40e5ad4df6ce..e01248ead24c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -194,7 +194,9 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); print('here'); if (fileSize != null) { + print('inside'); final Pointer pointer = Pointer.fromAddress(fileSize.ref.pointer.address); + print('pointer made'); return pointer.value; } //return figleSize?.ref.pointer.cast().value; From dfb7ee55e3c74e5ffc9b8306dab07169d76309ce Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:33:37 -0400 Subject: [PATCH 278/398] try long again --- .../lib/src/darwin_scoped_storage_cross_file.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index e01248ead24c..0d1d3c4f3a27 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -195,7 +195,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile print('here'); if (fileSize != null) { print('inside'); - final Pointer pointer = Pointer.fromAddress(fileSize.ref.pointer.address); + print(fileSize.ref.pointer.address); + final pointer = Pointer.fromAddress(fileSize.ref.pointer.address); print('pointer made'); return pointer.value; } From ba16dfceb0a7c1e3bcc153b0e7e35179ca31f6b2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:31:25 -0400 Subject: [PATCH 279/398] try ot use nsnumber --- .../lib/src/darwin_scoped_storage_cross_file.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 0d1d3c4f3a27..aa6977d4a4ff 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -191,14 +191,16 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile if (firstObject != null) { final resource = PHAssetResource.as(firstObject); - final ObjCObject? fileSize = resource.valueForKey(NSString('fileSize')); + final ObjCObject? fileSize = resource.valueForKey('fileSize'.toNSString()); print('here'); if (fileSize != null) { - print('inside'); - print(fileSize.ref.pointer.address); - final pointer = Pointer.fromAddress(fileSize.ref.pointer.address); - print('pointer made'); - return pointer.value; + final b = NSNumber.as(fileSize); + return b.intValue; + // print('inside'); + // print(fileSize.ref.pointer.address); + // final pointer = Pointer.fromAddress(fileSize.ref.pointer.address); + // print('pointer made'); + // return pointer.value; } //return figleSize?.ref.pointer.cast().value; } From 83ae9342234aff46e4142edd3ad0a17d85b11d8a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 4 Jun 2026 14:35:43 -0400 Subject: [PATCH 280/398] use nsnumber --- .../lib/src/darwin_scoped_storage_cross_file.dart | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index aa6977d4a4ff..447942ee4000 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -192,17 +192,10 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile if (firstObject != null) { final resource = PHAssetResource.as(firstObject); final ObjCObject? fileSize = resource.valueForKey('fileSize'.toNSString()); - print('here'); + if (fileSize != null) { - final b = NSNumber.as(fileSize); - return b.intValue; - // print('inside'); - // print(fileSize.ref.pointer.address); - // final pointer = Pointer.fromAddress(fileSize.ref.pointer.address); - // print('pointer made'); - // return pointer.value; + return NSNumber.as(fileSize).intValue; } - //return figleSize?.ref.pointer.cast().value; } } From 148953a9420670ec1c9bf72a94a3b178838dba72 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:08:48 -0400 Subject: [PATCH 281/398] i think working algo --- .../src/darwin_scoped_storage_cross_file.dart | 118 ++++++++++++++---- 1 file changed, 92 insertions(+), 26 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 447942ee4000..7108986f7fff 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; +import 'dart:math'; import 'dart:ui'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -79,7 +80,7 @@ base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFi static final Finalizer _finalizer = Finalizer((String uri) { // Check that this is not called during a unit test. if (Platform.environment['FLUTTER_TEST'] != 'true') { - final NSURL? url = NSURL.URLWithString(NSString(uri)); + final NSURL? url = NSURL.URLWithString(uri.toNSString()); if (url != null) { url.stopAccessingSecurityScopedResource(); } @@ -127,7 +128,7 @@ base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFi @override Future canRead() async { return NSFileManager.getDefaultManager().isReadableFileAtPath( - NSString(Uri.file(params.uri).path), + Uri.file(params.uri).path.toNSString(), ); } @@ -139,7 +140,7 @@ base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFi @override Future startAccessingSecurityScopedResource() async { - final NSURL? url = NSURL.URLWithString(NSString(params.uri)); + final NSURL? url = NSURL.URLWithString(params.uri.toNSString()); if (url == null) { return false; } @@ -148,7 +149,7 @@ base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFi @override Future stopAccessingSecurityScopedResource() async { - final NSURL? url = NSURL.URLWithString(NSString(params.uri)); + final NSURL? url = NSURL.URLWithString(params.uri.toNSString()); if (url != null) { url.stopAccessingSecurityScopedResource(); } @@ -185,17 +186,11 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile @override Future length() async { - if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { - final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); - final ObjCObject? firstObject = resources.firstObject; - - if (firstObject != null) { - final resource = PHAssetResource.as(firstObject); - final ObjCObject? fileSize = resource.valueForKey('fileSize'.toNSString()); + if (_tryGetAssetResource(identifier: params.uri) case final PHAssetResource resource) { + final ObjCObject? fileSize = resource.valueForKey('fileSize'.toNSString()); - if (fileSize != null) { - return NSNumber.as(fileSize).intValue; - } + if (fileSize != null) { + return NSNumber.as(fileSize).intValue; } } @@ -203,7 +198,73 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } @override - Stream openRead([int? start, int? end]) => throw UnsupportedError(''); + Stream openRead([int? start, int? end]) { + assert(start == null || start >= 0); + assert(end == null || end >= (start ?? 0)); + + if (_tryGetAssetResource(identifier: params.uri) case final PHAssetResource resource) { + final PHAssetResourceManager resourceManager = PHAssetResourceManager.defaultManager(); + + final streamController = StreamController(); + var currentByteIndex = 0; + + void dataReceivedHandler(NSData data) { + final Uint8List bytes = _extractBytesToUint8List(data); + + runOnPlatformThread(() { + final int newByteIndex = currentByteIndex + bytes.length; + final int startOrZero = start ?? 0; + + if (end == null) { + if (currentByteIndex >= startOrZero) { + streamController.add(bytes); + } else { + if (newByteIndex > startOrZero) { + streamController.add(bytes.sublist(startOrZero - currentByteIndex)); + } + } + } else { + final int bytesLeftToRead = end - max(currentByteIndex, startOrZero); + + if (bytesLeftToRead > 0) { + if (currentByteIndex >= startOrZero) { + streamController.add(bytes.sublist(0, min(bytesLeftToRead, bytes.length))); + } else if (newByteIndex > startOrZero) { + streamController.add( + bytes.sublist( + startOrZero - currentByteIndex, + min(startOrZero - currentByteIndex + bytesLeftToRead, bytes.length), + ), + ); + } + } + } + + currentByteIndex = newByteIndex; + }); + } + + void completionHandler(NSError? error) { + runOnPlatformThread(() { + if (error != null) { + streamController.addError(Exception(error.localizedDescription.toDartString())); + } + + return streamController.close(); + }); + } + + resourceManager.requestDataForAssetResource( + resource, + dataReceivedHandler: ObjCBlock_ffiVoid_NSData.listener(dataReceivedHandler), + completionHandler: ObjCBlock_ffiVoid_NSError.listener(completionHandler), + ); + + return streamController.stream; + } + + throw Error(); + } @override Future readAsBytes() { @@ -242,9 +303,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } @override - Future readAsString({Encoding encoding = utf8}) async { - return encoding.decode(await readAsBytes()); - } + Future readAsString({Encoding encoding = utf8}) => encoding.decodeStream(openRead()); @override Future canRead() => exists(); @@ -254,14 +313,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile @override Future name() async { - if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { - final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); - final ObjCObject? firstObject = resources.firstObject; - - if (firstObject != null) { - final resource = PHAssetResource.as(firstObject); - return resource.originalFilename.toDartString(); - } + if (_tryGetAssetResource(identifier: params.uri) case final PHAssetResource resource) { + return resource.originalFilename.toDartString(); } return null; @@ -279,6 +332,19 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile return null; } + PHAssetResource? _tryGetAssetResource({required String identifier}) { + if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { + final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); + final ObjCObject? firstObject = resources.firstObject; + + if (firstObject != null) { + return PHAssetResource.as(firstObject); + } + } + + return null; + } + Uint8List _extractBytesToUint8List(NSData data) { if (data.length == 0) { return Uint8List(0); From c4e8634719414fd512ceb390db93040d450d5f5f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:20:38 -0400 Subject: [PATCH 282/398] prints --- .../lib/src/darwin_scoped_storage_cross_file.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 7108986f7fff..40c84e721cf3 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -216,7 +216,10 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final int startOrZero = start ?? 0; if (end == null) { + print('end null'); if (currentByteIndex >= startOrZero) { + print('add'); + print(bytes.length); streamController.add(bytes); } else { if (newByteIndex > startOrZero) { From 4a65aa9af76ec51b3516dabc231aa32666422fdd Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:38:36 -0400 Subject: [PATCH 283/398] add some prints --- .../lib/src/darwin_scoped_storage_cross_file.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 40c84e721cf3..c0c94be1ac7b 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -230,6 +230,9 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final int bytesLeftToRead = end - max(currentByteIndex, startOrZero); if (bytesLeftToRead > 0) { + // late final int bytesStart; + // late final int bytesEnd; + if (currentByteIndex >= startOrZero) { streamController.add(bytes.sublist(0, min(bytesLeftToRead, bytes.length))); } else if (newByteIndex > startOrZero) { @@ -250,8 +253,10 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile void completionHandler(NSError? error) { runOnPlatformThread(() { if (error != null) { + print('ERROR'); streamController.addError(Exception(error.localizedDescription.toDartString())); } + print('FINISHED'); return streamController.close(); }); From e6c3e59fdb021dd3575f1fa6ab93cca7de7a7a02 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:27:38 -0400 Subject: [PATCH 284/398] look at other resources --- .../src/darwin_scoped_storage_cross_file.dart | 9 +- .../lib/src/ffi_bindings.g.dart | 1477 +++++------------ .../cross_file_darwin/tool/ffigen.dart | 6 +- 3 files changed, 426 insertions(+), 1066 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index c0c94be1ac7b..74b3706fef78 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -216,7 +216,6 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final int startOrZero = start ?? 0; if (end == null) { - print('end null'); if (currentByteIndex >= startOrZero) { print('add'); print(bytes.length); @@ -253,10 +252,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile void completionHandler(NSError? error) { runOnPlatformThread(() { if (error != null) { - print('ERROR'); streamController.addError(Exception(error.localizedDescription.toDartString())); } - print('FINISHED'); return streamController.close(); }); @@ -345,6 +342,12 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); final ObjCObject? firstObject = resources.firstObject; + print('cfd: ${resources.count}'); + for (var index = 0; index < resources.count; index++) { + final resource = PHAssetResource.as(resources.objectAtIndex(index)); + print('cfd: ${resource.type}'); + } + if (firstObject != null) { return PHAssetResource.as(firstObject); } diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 3a3c9427e83f..2c24548865d1 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -6,11 +6,10 @@ import 'dart:ffi' as ffi; import 'package:objective_c/objective_c.dart' as objc; import 'package:ffi/ffi.dart' as pkg_ffi; -@ffi.Native< - ffi.Pointer Function(ffi.Pointer) ->(isLeaf: true) -external ffi.Pointer -_NativeLibrary_wrapListenerBlock_pfv6jd(ffi.Pointer block); +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer _NativeLibrary_wrapListenerBlock_pfv6jd( + ffi.Pointer block, +); @ffi.Native< ffi.Pointer Function( @@ -19,18 +18,16 @@ _NativeLibrary_wrapListenerBlock_pfv6jd(ffi.Pointer block); ffi.Pointer, ) >(isLeaf: true) -external ffi.Pointer -_NativeLibrary_wrapBlockingBlock_pfv6jd( +external ffi.Pointer _NativeLibrary_wrapBlockingBlock_pfv6jd( ffi.Pointer block, ffi.Pointer listnerBlock, ffi.Pointer context, ); -@ffi.Native< - ffi.Pointer Function(ffi.Pointer) ->(isLeaf: true) -external ffi.Pointer -_NativeLibrary_wrapListenerBlock_10c3wkj(ffi.Pointer block); +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer _NativeLibrary_wrapListenerBlock_10c3wkj( + ffi.Pointer block, +); @ffi.Native< ffi.Pointer Function( @@ -39,18 +36,16 @@ _NativeLibrary_wrapListenerBlock_10c3wkj(ffi.Pointer block); ffi.Pointer, ) >(isLeaf: true) -external ffi.Pointer -_NativeLibrary_wrapBlockingBlock_10c3wkj( +external ffi.Pointer _NativeLibrary_wrapBlockingBlock_10c3wkj( ffi.Pointer block, ffi.Pointer listnerBlock, ffi.Pointer context, ); -@ffi.Native< - ffi.Pointer Function(ffi.Pointer) ->(isLeaf: true) -external ffi.Pointer -_NativeLibrary_wrapListenerBlock_xtuoz7(ffi.Pointer block); +@ffi.Native Function(ffi.Pointer)>(isLeaf: true) +external ffi.Pointer _NativeLibrary_wrapListenerBlock_xtuoz7( + ffi.Pointer block, +); @ffi.Native< ffi.Pointer Function( @@ -59,8 +54,7 @@ _NativeLibrary_wrapListenerBlock_xtuoz7(ffi.Pointer block); ffi.Pointer, ) >(isLeaf: true) -external ffi.Pointer -_NativeLibrary_wrapBlockingBlock_xtuoz7( +external ffi.Pointer _NativeLibrary_wrapBlockingBlock_xtuoz7( ffi.Pointer block, ffi.Pointer listnerBlock, ffi.Pointer context, @@ -71,18 +65,10 @@ late final _sel_version = objc.registerName("version"); final _objc_msgSend_1hz7y9r = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.Long Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Long Function(ffi.Pointer, ffi.Pointer) > >() - .asFunction< - int Function( - ffi.Pointer, - ffi.Pointer, - ) - >(); + .asFunction, ffi.Pointer)>(); late final _sel_setVersion_ = objc.registerName("setVersion:"); final _objc_msgSend_4sp4xj = objc.msgSendPointer .cast< @@ -95,11 +81,7 @@ final _objc_msgSend_4sp4xj = objc.msgSendPointer > >() .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - int, - ) + void Function(ffi.Pointer, ffi.Pointer, int) >(); late final _sel_classForCoder = objc.registerName("classForCoder"); final _objc_msgSend_151sglz = objc.msgSendPointer @@ -117,9 +99,7 @@ final _objc_msgSend_151sglz = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_replacementObjectForCoder_ = objc.registerName( - "replacementObjectForCoder:", -); +late final _sel_replacementObjectForCoder_ = objc.registerName("replacementObjectForCoder:"); final _objc_msgSend_1sotr3r = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -137,9 +117,7 @@ final _objc_msgSend_1sotr3r = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_awakeAfterUsingCoder_ = objc.registerName( - "awakeAfterUsingCoder:", -); +late final _sel_awakeAfterUsingCoder_ = objc.registerName("awakeAfterUsingCoder:"); /// NSCoderMethods extension NSCoderMethods on objc.NSObject { @@ -155,9 +133,7 @@ extension NSCoderMethods on objc.NSObject { _sel_awakeAfterUsingCoder_, coder.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: false, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } /// classForCoder @@ -183,9 +159,7 @@ extension NSCoderMethods on objc.NSObject { _sel_replacementObjectForCoder_, coder.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// setVersion: @@ -237,17 +211,11 @@ extension NSDeprecatedMethods on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - _class_NSObject, - _sel_poseAsClass_, - aClass.ref.pointer, - ); + _objc_msgSend_xtuoz7(_class_NSObject, _sel_poseAsClass_, aClass.ref.pointer); } } -late final _sel_autoContentAccessingProxy = objc.registerName( - "autoContentAccessingProxy", -); +late final _sel_autoContentAccessingProxy = objc.registerName("autoContentAccessingProxy"); /// NSDiscardableContentProxy extension NSDiscardableContentProxy on objc.NSObject { @@ -258,18 +226,13 @@ extension NSDiscardableContentProxy on objc.NSObject { iOS: (false, (4, 0, 0)), macOS: (false, (10, 6, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_autoContentAccessingProxy, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_autoContentAccessingProxy); return objc.ObjCObject($ret, retain: true, release: true); } } -late final _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_ = - objc.registerName( - "attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:", - ); +late final _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_ = objc + .registerName("attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:"); final _objc_msgSend_10txwc9 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -321,10 +284,7 @@ final _objc_msgSend_z7gxsm = objc.msgSendPointer /// NSErrorRecoveryAttempting extension NSErrorRecoveryAttempting on objc.NSObject { /// attemptRecoveryFromError:optionIndex: - bool attemptRecoveryFromError( - objc.NSError error, { - required int optionIndex, - }) { + bool attemptRecoveryFromError(objc.NSError error, {required int optionIndex}) { objc.checkOsVersionInternal( 'NSObject.attemptRecoveryFromError:optionIndex:', iOS: (false, (2, 0, 0)), @@ -363,8 +323,9 @@ extension NSErrorRecoveryAttempting on objc.NSObject { } } -late final _sel_performSelector_withObject_afterDelay_inModes_ = objc - .registerName("performSelector:withObject:afterDelay:inModes:"); +late final _sel_performSelector_withObject_afterDelay_inModes_ = objc.registerName( + "performSelector:withObject:afterDelay:inModes:", +); final _objc_msgSend_t8ajot = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -412,8 +373,9 @@ final _objc_msgSend_7ql5kn = objc.msgSendPointer double, ) >(); -late final _sel_cancelPreviousPerformRequestsWithTarget_selector_object_ = objc - .registerName("cancelPreviousPerformRequestsWithTarget:selector:object:"); +late final _sel_cancelPreviousPerformRequestsWithTarget_selector_object_ = objc.registerName( + "cancelPreviousPerformRequestsWithTarget:selector:object:", +); final _objc_msgSend_1ygbbzi = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -540,12 +502,8 @@ final _objc_msgSend_pfv6jd = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_URLResourceDidFinishLoading_ = objc.registerName( - "URLResourceDidFinishLoading:", -); -late final _sel_URLResourceDidCancelLoading_ = objc.registerName( - "URLResourceDidCancelLoading:", -); +late final _sel_URLResourceDidFinishLoading_ = objc.registerName("URLResourceDidFinishLoading:"); +late final _sel_URLResourceDidCancelLoading_ = objc.registerName("URLResourceDidCancelLoading:"); late final _sel_URL_resourceDidFailLoadingWithReason_ = objc.registerName( "URL:resourceDidFailLoadingWithReason:", ); @@ -553,10 +511,7 @@ late final _sel_URL_resourceDidFailLoadingWithReason_ = objc.registerName( /// NSURLClient extension NSURLClient on objc.NSObject { /// URL:resourceDataDidBecomeAvailable: - void URL( - objc.NSURL sender, { - required objc.NSData resourceDataDidBecomeAvailable, - }) { + void URL(objc.NSURL sender, {required objc.NSData resourceDataDidBecomeAvailable}) { objc.checkOsVersionInternal( 'NSObject.URL:resourceDataDidBecomeAvailable:', iOS: (false, (2, 0, 0)), @@ -571,10 +526,7 @@ extension NSURLClient on objc.NSObject { } /// URL:resourceDidFailLoadingWithReason: - void URL$1( - objc.NSURL sender, { - required objc.NSString resourceDidFailLoadingWithReason, - }) { + void URL$1(objc.NSURL sender, {required objc.NSString resourceDidFailLoadingWithReason}) { objc.checkOsVersionInternal( 'NSObject.URL:resourceDidFailLoadingWithReason:', iOS: (false, (2, 0, 0)), @@ -637,16 +589,10 @@ final _objc_msgSend_19nvye5 = objc.msgSendPointer ) >(); late final _sel_defaultManager = objc.registerName("defaultManager"); -late final _sel_isReadableFileAtPath_ = objc.registerName( - "isReadableFileAtPath:", -); -late final _sel_homeDirectoryForCurrentUser = objc.registerName( - "homeDirectoryForCurrentUser", -); +late final _sel_isReadableFileAtPath_ = objc.registerName("isReadableFileAtPath:"); +late final _sel_homeDirectoryForCurrentUser = objc.registerName("homeDirectoryForCurrentUser"); late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); -late final _sel_homeDirectoryForUser_ = objc.registerName( - "homeDirectoryForUser:", -); +late final _sel_homeDirectoryForUser_ = objc.registerName("homeDirectoryForUser:"); /// NSUserInformation extension NSUserInformation on NSFileManager { @@ -657,10 +603,7 @@ extension NSUserInformation on NSFileManager { iOS: (true, null), macOS: (false, (10, 12, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_homeDirectoryForCurrentUser, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_homeDirectoryForCurrentUser); return objc.NSURL.fromPointer($ret, retain: true, release: true); } @@ -676,9 +619,7 @@ extension NSUserInformation on NSFileManager { _sel_homeDirectoryForUser_, userName.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.NSURL.fromPointer($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.NSURL.fromPointer($ret, retain: true, release: true); } /// temporaryDirectory @@ -688,17 +629,13 @@ extension NSUserInformation on NSFileManager { iOS: (false, (10, 0, 0)), macOS: (false, (10, 12, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_temporaryDirectory, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_temporaryDirectory); return objc.NSURL.fromPointer($ret, retain: true, release: true); } } /// NSFileManager -extension type NSFileManager._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { +extension type NSFileManager._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { /// Constructs a [NSFileManager] that points to the same underlying object as [other]. NSFileManager.as(objc.ObjCObject other) : object$ = other { assert(isA(object$)); @@ -714,18 +651,12 @@ extension type NSFileManager._(objc.ObjCObject object$) } /// Returns whether [obj] is an instance of [NSFileManager]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_NSFileManager, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_NSFileManager); /// defaultManager static NSFileManager getDefaultManager() { - final $ret = _objc_msgSend_151sglz( - _class_NSFileManager, - _sel_defaultManager, - ); + final $ret = _objc_msgSend_151sglz(_class_NSFileManager, _sel_defaultManager); return NSFileManager.fromPointer($ret, retain: true, release: true); } } @@ -733,11 +664,7 @@ extension type NSFileManager._(objc.ObjCObject object$) extension NSFileManager$Methods on NSFileManager { /// isReadableFileAtPath: bool isReadableFileAtPath(objc.NSString path) { - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isReadableFileAtPath_, - path.ref.pointer, - ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isReadableFileAtPath_, path.ref.pointer); } } @@ -763,17 +690,12 @@ final _objc_msgSend_1lsax7n = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_fileManager_willProcessPath_ = objc.registerName( - "fileManager:willProcessPath:", -); +late final _sel_fileManager_willProcessPath_ = objc.registerName("fileManager:willProcessPath:"); /// NSCopyLinkMoveHandler extension NSCopyLinkMoveHandler on objc.NSObject { /// fileManager:shouldProceedAfterError: - bool fileManager( - NSFileManager fm, { - required objc.NSDictionary shouldProceedAfterError, - }) { + bool fileManager(NSFileManager fm, {required objc.NSDictionary shouldProceedAfterError}) { objc.checkOsVersionInternal( 'NSObject.fileManager:shouldProceedAfterError:', iOS: (false, (2, 0, 0)), @@ -788,10 +710,7 @@ extension NSCopyLinkMoveHandler on objc.NSObject { } /// fileManager:willProcessPath: - void fileManager$1( - NSFileManager fm, { - required objc.NSString willProcessPath, - }) { + void fileManager$1(NSFileManager fm, {required objc.NSString willProcessPath}) { objc.checkOsVersionInternal( 'NSObject.fileManager:willProcessPath:', iOS: (false, (2, 0, 0)), @@ -812,23 +731,13 @@ late final _sel_accessInstanceVariablesDirectly = objc.registerName( final _objc_msgSend_91o635 = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Bool Function(ffi.Pointer, ffi.Pointer) > >() - .asFunction< - bool Function( - ffi.Pointer, - ffi.Pointer, - ) - >(); + .asFunction, ffi.Pointer)>(); late final _sel_valueForKey_ = objc.registerName("valueForKey:"); late final _sel_setValue_forKey_ = objc.registerName("setValue:forKey:"); -late final _sel_validateValue_forKey_error_ = objc.registerName( - "validateValue:forKey:error:", -); +late final _sel_validateValue_forKey_error_ = objc.registerName("validateValue:forKey:error:"); final _objc_msgSend_1j9bhml = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -850,41 +759,23 @@ final _objc_msgSend_1j9bhml = objc.msgSendPointer ffi.Pointer>, ) >(); -late final _sel_mutableArrayValueForKey_ = objc.registerName( - "mutableArrayValueForKey:", -); -late final _sel_mutableOrderedSetValueForKey_ = objc.registerName( - "mutableOrderedSetValueForKey:", -); -late final _sel_mutableSetValueForKey_ = objc.registerName( - "mutableSetValueForKey:", -); +late final _sel_mutableArrayValueForKey_ = objc.registerName("mutableArrayValueForKey:"); +late final _sel_mutableOrderedSetValueForKey_ = objc.registerName("mutableOrderedSetValueForKey:"); +late final _sel_mutableSetValueForKey_ = objc.registerName("mutableSetValueForKey:"); late final _sel_valueForKeyPath_ = objc.registerName("valueForKeyPath:"); -late final _sel_setValue_forKeyPath_ = objc.registerName( - "setValue:forKeyPath:", -); +late final _sel_setValue_forKeyPath_ = objc.registerName("setValue:forKeyPath:"); late final _sel_validateValue_forKeyPath_error_ = objc.registerName( "validateValue:forKeyPath:error:", ); -late final _sel_mutableArrayValueForKeyPath_ = objc.registerName( - "mutableArrayValueForKeyPath:", -); +late final _sel_mutableArrayValueForKeyPath_ = objc.registerName("mutableArrayValueForKeyPath:"); late final _sel_mutableOrderedSetValueForKeyPath_ = objc.registerName( "mutableOrderedSetValueForKeyPath:", ); -late final _sel_mutableSetValueForKeyPath_ = objc.registerName( - "mutableSetValueForKeyPath:", -); -late final _sel_valueForUndefinedKey_ = objc.registerName( - "valueForUndefinedKey:", -); -late final _sel_setValue_forUndefinedKey_ = objc.registerName( - "setValue:forUndefinedKey:", -); +late final _sel_mutableSetValueForKeyPath_ = objc.registerName("mutableSetValueForKeyPath:"); +late final _sel_valueForUndefinedKey_ = objc.registerName("valueForUndefinedKey:"); +late final _sel_setValue_forUndefinedKey_ = objc.registerName("setValue:forUndefinedKey:"); late final _sel_setNilValueForKey_ = objc.registerName("setNilValueForKey:"); -late final _sel_dictionaryWithValuesForKeys_ = objc.registerName( - "dictionaryWithValuesForKeys:", -); +late final _sel_dictionaryWithValuesForKeys_ = objc.registerName("dictionaryWithValuesForKeys:"); late final _sel_setValuesForKeysWithDictionary_ = objc.registerName( "setValuesForKeysWithDictionary:", ); @@ -948,17 +839,11 @@ extension NSKeyValueCoding on objc.NSObject { _sel_mutableOrderedSetValueForKey_, key.ref.pointer, ); - return objc.NSMutableOrderedSet.fromPointer( - $ret, - retain: true, - release: true, - ); + return objc.NSMutableOrderedSet.fromPointer($ret, retain: true, release: true); } /// mutableOrderedSetValueForKeyPath: - objc.NSMutableOrderedSet mutableOrderedSetValueForKeyPath( - objc.NSString keyPath, - ) { + objc.NSMutableOrderedSet mutableOrderedSetValueForKeyPath(objc.NSString keyPath) { objc.checkOsVersionInternal( 'NSObject.mutableOrderedSetValueForKeyPath:', iOS: (false, (5, 0, 0)), @@ -969,11 +854,7 @@ extension NSKeyValueCoding on objc.NSObject { _sel_mutableOrderedSetValueForKeyPath_, keyPath.ref.pointer, ); - return objc.NSMutableOrderedSet.fromPointer( - $ret, - retain: true, - release: true, - ); + return objc.NSMutableOrderedSet.fromPointer($ret, retain: true, release: true); } /// mutableSetValueForKey: @@ -1013,11 +894,7 @@ extension NSKeyValueCoding on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_setNilValueForKey_, - key.ref.pointer, - ); + _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_setNilValueForKey_, key.ref.pointer); } /// setValue:forKey: @@ -1051,10 +928,7 @@ extension NSKeyValueCoding on objc.NSObject { } /// setValue:forUndefinedKey: - void setValue$2( - objc.ObjCObject? value, { - required objc.NSString forUndefinedKey, - }) { + void setValue$2(objc.ObjCObject? value, {required objc.NSString forUndefinedKey}) { objc.checkOsVersionInternal( 'NSObject.setValue:forUndefinedKey:', iOS: (false, (2, 0, 0)), @@ -1141,14 +1015,8 @@ extension NSKeyValueCoding on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_valueForKey_, - key.ref.pointer, - ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + final $ret = _objc_msgSend_1sotr3r(object$.ref.pointer, _sel_valueForKey_, key.ref.pointer); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// valueForKeyPath: @@ -1163,9 +1031,7 @@ extension NSKeyValueCoding on objc.NSObject { _sel_valueForKeyPath_, keyPath.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// valueForUndefinedKey: @@ -1180,9 +1046,7 @@ extension NSKeyValueCoding on objc.NSObject { _sel_valueForUndefinedKey_, key.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// accessInstanceVariablesDirectly @@ -1192,35 +1056,22 @@ extension NSKeyValueCoding on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_91o635( - _class_NSObject, - _sel_accessInstanceVariablesDirectly, - ); + return _objc_msgSend_91o635(_class_NSObject, _sel_accessInstanceVariablesDirectly); } } late final _sel_useStoredAccessor = objc.registerName("useStoredAccessor"); late final _sel_storedValueForKey_ = objc.registerName("storedValueForKey:"); -late final _sel_takeStoredValue_forKey_ = objc.registerName( - "takeStoredValue:forKey:", -); +late final _sel_takeStoredValue_forKey_ = objc.registerName("takeStoredValue:forKey:"); late final _sel_takeValue_forKey_ = objc.registerName("takeValue:forKey:"); -late final _sel_takeValue_forKeyPath_ = objc.registerName( - "takeValue:forKeyPath:", -); -late final _sel_handleQueryWithUnboundKey_ = objc.registerName( - "handleQueryWithUnboundKey:", -); +late final _sel_takeValue_forKeyPath_ = objc.registerName("takeValue:forKeyPath:"); +late final _sel_handleQueryWithUnboundKey_ = objc.registerName("handleQueryWithUnboundKey:"); late final _sel_handleTakeValue_forUnboundKey_ = objc.registerName( "handleTakeValue:forUnboundKey:", ); -late final _sel_unableToSetNilForKey_ = objc.registerName( - "unableToSetNilForKey:", -); +late final _sel_unableToSetNilForKey_ = objc.registerName("unableToSetNilForKey:"); late final _sel_valuesForKeys_ = objc.registerName("valuesForKeys:"); -late final _sel_takeValuesFromDictionary_ = objc.registerName( - "takeValuesFromDictionary:", -); +late final _sel_takeValuesFromDictionary_ = objc.registerName("takeValuesFromDictionary:"); /// NSDeprecatedKeyValueCoding extension NSDeprecatedKeyValueCoding on objc.NSObject { @@ -1236,16 +1087,11 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { _sel_handleQueryWithUnboundKey_, key.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// handleTakeValue:forUnboundKey: - void handleTakeValue( - objc.ObjCObject? value, { - required objc.NSString forUnboundKey, - }) { + void handleTakeValue(objc.ObjCObject? value, {required objc.NSString forUnboundKey}) { objc.checkOsVersionInternal( 'NSObject.handleTakeValue:forUnboundKey:', iOS: (false, (2, 0, 0)), @@ -1271,16 +1117,11 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { _sel_storedValueForKey_, key.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// takeStoredValue:forKey: - void takeStoredValue( - objc.ObjCObject? value, { - required objc.NSString forKey, - }) { + void takeStoredValue(objc.ObjCObject? value, {required objc.NSString forKey}) { objc.checkOsVersionInternal( 'NSObject.takeStoredValue:forKey:', iOS: (false, (2, 0, 0)), @@ -1310,10 +1151,7 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { } /// takeValue:forKeyPath: - void takeValue$1( - objc.ObjCObject? value, { - required objc.NSString forKeyPath, - }) { + void takeValue$1(objc.ObjCObject? value, {required objc.NSString forKeyPath}) { objc.checkOsVersionInternal( 'NSObject.takeValue:forKeyPath:', iOS: (false, (2, 0, 0)), @@ -1348,11 +1186,7 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_unableToSetNilForKey_, - key.ref.pointer, - ); + _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_unableToSetNilForKey_, key.ref.pointer); } /// valuesForKeys: @@ -1362,11 +1196,7 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_valuesForKeys_, - keys.ref.pointer, - ); + final $ret = _objc_msgSend_1sotr3r(object$.ref.pointer, _sel_valuesForKeys_, keys.ref.pointer); return objc.NSDictionary.fromPointer($ret, retain: true, release: true); } @@ -1381,8 +1211,9 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { } } -late final _sel_observeValueForKeyPath_ofObject_change_context_ = objc - .registerName("observeValueForKeyPath:ofObject:change:context:"); +late final _sel_observeValueForKeyPath_ofObject_change_context_ = objc.registerName( + "observeValueForKeyPath:ofObject:change:context:", +); final _objc_msgSend_1pl4k3n = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -1482,9 +1313,7 @@ final _objc_msgSend_1jed5jl = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_removeObserver_forKeyPath_ = objc.registerName( - "removeObserver:forKeyPath:", -); +late final _sel_removeObserver_forKeyPath_ = objc.registerName("removeObserver:forKeyPath:"); /// NSKeyValueObserverRegistration extension NSKeyValueObserverRegistration on objc.NSObject { @@ -1511,10 +1340,7 @@ extension NSKeyValueObserverRegistration on objc.NSObject { } /// removeObserver:forKeyPath: - void removeObserver( - objc.NSObject observer, { - required objc.NSString forKeyPath, - }) { + void removeObserver(objc.NSObject observer, {required objc.NSString forKeyPath}) { objc.checkOsVersionInternal( 'NSObject.removeObserver:forKeyPath:', iOS: (false, (2, 0, 0)), @@ -1549,12 +1375,8 @@ extension NSKeyValueObserverRegistration on objc.NSObject { } } -late final _sel_willChangeValueForKey_ = objc.registerName( - "willChangeValueForKey:", -); -late final _sel_didChangeValueForKey_ = objc.registerName( - "didChangeValueForKey:", -); +late final _sel_willChangeValueForKey_ = objc.registerName("willChangeValueForKey:"); +late final _sel_didChangeValueForKey_ = objc.registerName("didChangeValueForKey:"); late final _sel_willChange_valuesAtIndexes_forKey_ = objc.registerName( "willChange:valuesAtIndexes:forKey:", ); @@ -1582,8 +1404,9 @@ final _objc_msgSend_1diehjo = objc.msgSendPointer late final _sel_didChange_valuesAtIndexes_forKey_ = objc.registerName( "didChange:valuesAtIndexes:forKey:", ); -late final _sel_willChangeValueForKey_withSetMutation_usingObjects_ = objc - .registerName("willChangeValueForKey:withSetMutation:usingObjects:"); +late final _sel_willChangeValueForKey_withSetMutation_usingObjects_ = objc.registerName( + "willChangeValueForKey:withSetMutation:usingObjects:", +); final _objc_msgSend_7w1jp7 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -1605,8 +1428,9 @@ final _objc_msgSend_7w1jp7 = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_didChangeValueForKey_withSetMutation_usingObjects_ = objc - .registerName("didChangeValueForKey:withSetMutation:usingObjects:"); +late final _sel_didChangeValueForKey_withSetMutation_usingObjects_ = objc.registerName( + "didChangeValueForKey:withSetMutation:usingObjects:", +); /// NSKeyValueObserverNotification extension NSKeyValueObserverNotification on objc.NSObject { @@ -1637,11 +1461,7 @@ extension NSKeyValueObserverNotification on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_didChangeValueForKey_, - key.ref.pointer, - ); + _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_didChangeValueForKey_, key.ref.pointer); } /// didChangeValueForKey:withSetMutation:usingObjects: @@ -1691,11 +1511,7 @@ extension NSKeyValueObserverNotification on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_willChangeValueForKey_, - key.ref.pointer, - ); + _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_willChangeValueForKey_, key.ref.pointer); } /// willChangeValueForKey:withSetMutation:usingObjects: @@ -1812,8 +1628,9 @@ extension NSKeyValueObservingCustomization on objc.NSObject { } } -late final _sel_setKeys_triggerChangeNotificationsForDependentKey_ = objc - .registerName("setKeys:triggerChangeNotificationsForDependentKey:"); +late final _sel_setKeys_triggerChangeNotificationsForDependentKey_ = objc.registerName( + "setKeys:triggerChangeNotificationsForDependentKey:", +); /// NSDeprecatedKeyValueObservingCustomization extension NSDeprecatedKeyValueObservingCustomization on objc.NSObject { @@ -1843,8 +1660,7 @@ extension NSDeprecatedKeyValueObservingCustomization on objc.NSObject { extension type NSKeyValueSharedObserversSnapshot._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { /// Constructs a [NSKeyValueSharedObserversSnapshot] that points to the same underlying object as [other]. - NSKeyValueSharedObserversSnapshot.as(objc.ObjCObject other) - : object$ = other { + NSKeyValueSharedObserversSnapshot.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( 'NSKeyValueSharedObserversSnapshot', iOS: (false, (18, 0, 0)), @@ -1889,8 +1705,7 @@ extension NSKeyValueSharedObserverRegistration on objc.NSObject { /// NSKeyedArchiver in your config's objc-interfaces list. /// /// NSKeyedArchiver -extension type NSKeyedArchiver._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSCoder { +extension type NSKeyedArchiver._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { /// Constructs a [NSKeyedArchiver] that points to the same underlying object as [other]. NSKeyedArchiver.as(objc.ObjCObject other) : object$ = other {} @@ -1902,9 +1717,7 @@ extension type NSKeyedArchiver._(objc.ObjCObject object$) }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} } -late final _sel_classForKeyedArchiver = objc.registerName( - "classForKeyedArchiver", -); +late final _sel_classForKeyedArchiver = objc.registerName("classForKeyedArchiver"); late final _sel_replacementObjectForKeyedArchiver_ = objc.registerName( "replacementObjectForKeyedArchiver:", ); @@ -1921,13 +1734,8 @@ extension NSKeyedArchiverObjectSubstitution on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_classForKeyedArchiver, - ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForKeyedArchiver); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// replacementObjectForKeyedArchiver: @@ -1942,9 +1750,7 @@ extension NSKeyedArchiverObjectSubstitution on objc.NSObject { _sel_replacementObjectForKeyedArchiver_, archiver.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// classFallbacksForKeyedArchiver @@ -1954,17 +1760,12 @@ extension NSKeyedArchiverObjectSubstitution on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - _class_NSObject, - _sel_classFallbacksForKeyedArchiver, - ); + final $ret = _objc_msgSend_151sglz(_class_NSObject, _sel_classFallbacksForKeyedArchiver); return objc.NSArray.fromPointer($ret, retain: true, release: true); } } -late final _sel_classForKeyedUnarchiver = objc.registerName( - "classForKeyedUnarchiver", -); +late final _sel_classForKeyedUnarchiver = objc.registerName("classForKeyedUnarchiver"); /// NSKeyedUnarchiverObjectSubstitution extension NSKeyedUnarchiverObjectSubstitution on objc.NSObject { @@ -1975,10 +1776,7 @@ extension NSKeyedUnarchiverObjectSubstitution on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - _class_NSObject, - _sel_classForKeyedUnarchiver, - ); + final $ret = _objc_msgSend_151sglz(_class_NSObject, _sel_classForKeyedUnarchiver); return objc.ObjCObject($ret, retain: true, release: true); } } @@ -1987,8 +1785,7 @@ extension NSKeyedUnarchiverObjectSubstitution on objc.NSObject { /// NSThread in your config's objc-interfaces list. /// /// NSThread -extension type NSThread._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { +extension type NSThread._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { /// Constructs a [NSThread] that points to the same underlying object as [other]. NSThread.as(objc.ObjCObject other) : object$ = other {} @@ -2000,10 +1797,9 @@ extension type NSThread._(objc.ObjCObject object$) }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} } -late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_ = - objc.registerName( - "performSelectorOnMainThread:withObject:waitUntilDone:modes:", - ); +late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_ = objc.registerName( + "performSelectorOnMainThread:withObject:waitUntilDone:modes:", +); final _objc_msgSend_1fdou4m = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -2027,8 +1823,9 @@ final _objc_msgSend_1fdou4m = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_ = objc - .registerName("performSelectorOnMainThread:withObject:waitUntilDone:"); +late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_ = objc.registerName( + "performSelectorOnMainThread:withObject:waitUntilDone:", +); final _objc_msgSend_tsocn4 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -2050,8 +1847,9 @@ final _objc_msgSend_tsocn4 = objc.msgSendPointer bool, ) >(); -late final _sel_performSelector_onThread_withObject_waitUntilDone_modes_ = objc - .registerName("performSelector:onThread:withObject:waitUntilDone:modes:"); +late final _sel_performSelector_onThread_withObject_waitUntilDone_modes_ = objc.registerName( + "performSelector:onThread:withObject:waitUntilDone:modes:", +); final _objc_msgSend_1cc1buo = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -2077,8 +1875,9 @@ final _objc_msgSend_1cc1buo = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_performSelector_onThread_withObject_waitUntilDone_ = objc - .registerName("performSelector:onThread:withObject:waitUntilDone:"); +late final _sel_performSelector_onThread_withObject_waitUntilDone_ = objc.registerName( + "performSelector:onThread:withObject:waitUntilDone:", +); final _objc_msgSend_1whyima = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -2238,15 +2037,10 @@ extension NSThreadPerformAdditions on objc.NSObject { /// NSArchiver in your config's objc-interfaces list. /// /// NSArchiver -extension type NSArchiver._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSCoder { +extension type NSArchiver._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { /// Constructs a [NSArchiver] that points to the same underlying object as [other]. NSArchiver.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'NSArchiver', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); + objc.checkOsVersionInternal('NSArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); } /// Constructs a [NSArchiver] that wraps the given raw object pointer. @@ -2255,18 +2049,12 @@ extension type NSArchiver._(objc.ObjCObject object$) bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'NSArchiver', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); + objc.checkOsVersionInternal('NSArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); } } late final _sel_classForArchiver = objc.registerName("classForArchiver"); -late final _sel_replacementObjectForArchiver_ = objc.registerName( - "replacementObjectForArchiver:", -); +late final _sel_replacementObjectForArchiver_ = objc.registerName("replacementObjectForArchiver:"); /// NSArchiverCallback extension NSArchiverCallback on objc.NSObject { @@ -2277,13 +2065,8 @@ extension NSArchiverCallback on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_classForArchiver, - ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForArchiver); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// replacementObjectForArchiver: @@ -2298,9 +2081,7 @@ extension NSArchiverCallback on objc.NSObject { _sel_replacementObjectForArchiver_, archiver.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } } @@ -2308,15 +2089,10 @@ extension NSArchiverCallback on objc.NSObject { /// NSPortCoder in your config's objc-interfaces list. /// /// NSPortCoder -extension type NSPortCoder._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSCoder { +extension type NSPortCoder._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { /// Constructs a [NSPortCoder] that points to the same underlying object as [other]. NSPortCoder.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'NSPortCoder', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); + objc.checkOsVersionInternal('NSPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); } /// Constructs a [NSPortCoder] that wraps the given raw object pointer. @@ -2325,11 +2101,7 @@ extension type NSPortCoder._(objc.ObjCObject object$) bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'NSPortCoder', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); + objc.checkOsVersionInternal('NSPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); } } @@ -2347,10 +2119,7 @@ extension NSDistributedObjects on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_classForPortCoder, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForPortCoder); return objc.ObjCObject($ret, retain: true, release: true); } @@ -2366,9 +2135,7 @@ extension NSDistributedObjects on objc.NSObject { _sel_replacementObjectForPortCoder_, coder.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } } @@ -2391,15 +2158,9 @@ extension type NSClassDescription._(objc.ObjCObject object$) late final _sel_classDescription = objc.registerName("classDescription"); late final _sel_attributeKeys = objc.registerName("attributeKeys"); -late final _sel_toOneRelationshipKeys = objc.registerName( - "toOneRelationshipKeys", -); -late final _sel_toManyRelationshipKeys = objc.registerName( - "toManyRelationshipKeys", -); -late final _sel_inverseForRelationshipKey_ = objc.registerName( - "inverseForRelationshipKey:", -); +late final _sel_toOneRelationshipKeys = objc.registerName("toOneRelationshipKeys"); +late final _sel_toManyRelationshipKeys = objc.registerName("toManyRelationshipKeys"); +late final _sel_inverseForRelationshipKey_ = objc.registerName("inverseForRelationshipKey:"); /// NSClassDescriptionPrimitives extension NSClassDescriptionPrimitives on objc.NSObject { @@ -2421,10 +2182,7 @@ extension NSClassDescriptionPrimitives on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_classDescription, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classDescription); return NSClassDescription.fromPointer($ret, retain: true, release: true); } @@ -2440,9 +2198,7 @@ extension NSClassDescriptionPrimitives on objc.NSObject { _sel_inverseForRelationshipKey_, relationshipKey.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.NSString.fromPointer($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); } /// toManyRelationshipKeys @@ -2452,10 +2208,7 @@ extension NSClassDescriptionPrimitives on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_toManyRelationshipKeys, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_toManyRelationshipKeys); return objc.NSArray.fromPointer($ret, retain: true, release: true); } @@ -2466,10 +2219,7 @@ extension NSClassDescriptionPrimitives on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_toOneRelationshipKeys, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_toOneRelationshipKeys); return objc.NSArray.fromPointer($ret, retain: true, release: true); } } @@ -2491,13 +2241,9 @@ extension type NSScriptObjectSpecifier._(objc.ObjCObject object$) }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} } -late final _sel_scriptingValueForSpecifier_ = objc.registerName( - "scriptingValueForSpecifier:", -); +late final _sel_scriptingValueForSpecifier_ = objc.registerName("scriptingValueForSpecifier:"); late final _sel_scriptingProperties = objc.registerName("scriptingProperties"); -late final _sel_setScriptingProperties_ = objc.registerName( - "setScriptingProperties:", -); +late final _sel_setScriptingProperties_ = objc.registerName("setScriptingProperties:"); late final _sel_copyScriptingValue_forKey_withProperties_ = objc.registerName( "copyScriptingValue:forKey:withProperties:", ); @@ -2522,10 +2268,8 @@ final _objc_msgSend_11spmsz = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_ = - objc.registerName( - "newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:", - ); +late final _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_ = objc + .registerName("newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:"); final _objc_msgSend_s92gih = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -2570,9 +2314,7 @@ extension NSScripting on objc.NSObject { forKey.ref.pointer, withProperties.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: false, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } /// newScriptingObjectOfClass:forValueForKey:withContentsValue:properties: @@ -2595,9 +2337,7 @@ extension NSScripting on objc.NSObject { withContentsValue?.ref.pointer ?? ffi.nullptr, properties.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: false, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } /// scriptingProperties @@ -2607,19 +2347,14 @@ extension NSScripting on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_scriptingProperties, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_scriptingProperties); return $ret.address == 0 ? null : objc.NSDictionary.fromPointer($ret, retain: true, release: true); } /// scriptingValueForSpecifier: - objc.ObjCObject? scriptingValueForSpecifier( - NSScriptObjectSpecifier objectSpecifier, - ) { + objc.ObjCObject? scriptingValueForSpecifier(NSScriptObjectSpecifier objectSpecifier) { objc.checkOsVersionInternal( 'NSObject.scriptingValueForSpecifier:', iOS: (true, null), @@ -2630,9 +2365,7 @@ extension NSScripting on objc.NSObject { _sel_scriptingValueForSpecifier_, objectSpecifier.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// setScriptingProperties: @@ -2654,18 +2387,10 @@ late final _sel_classCode = objc.registerName("classCode"); final _objc_msgSend_3pyzne = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.UnsignedInt Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.UnsignedInt Function(ffi.Pointer, ffi.Pointer) > >() - .asFunction< - int Function( - ffi.Pointer, - ffi.Pointer, - ) - >(); + .asFunction, ffi.Pointer)>(); late final _sel_className = objc.registerName("className"); /// NSScriptClassDescription @@ -2785,8 +2510,9 @@ final _objc_msgSend_1gypgok = objc.msgSendPointer ffi.Pointer, ) >(); -late final _sel_replaceValueAtIndex_inPropertyWithKey_withValue_ = objc - .registerName("replaceValueAtIndex:inPropertyWithKey:withValue:"); +late final _sel_replaceValueAtIndex_inPropertyWithKey_withValue_ = objc.registerName( + "replaceValueAtIndex:inPropertyWithKey:withValue:", +); final _objc_msgSend_rutu22 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -2816,10 +2542,7 @@ late final _sel_coerceValue_forKey_ = objc.registerName("coerceValue:forKey:"); /// NSScriptKeyValueCoding extension NSScriptKeyValueCoding on objc.NSObject { /// coerceValue:forKey: - objc.ObjCObject? coerceValue( - objc.ObjCObject? value, { - required objc.NSString forKey, - }) { + objc.ObjCObject? coerceValue(objc.ObjCObject? value, {required objc.NSString forKey}) { objc.checkOsVersionInternal( 'NSObject.coerceValue:forKey:', iOS: (false, (2, 0, 0)), @@ -2831,9 +2554,7 @@ extension NSScriptKeyValueCoding on objc.NSObject { value?.ref.pointer ?? ffi.nullptr, forKey.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// insertValue:atIndex:inPropertyWithKey: @@ -2857,10 +2578,7 @@ extension NSScriptKeyValueCoding on objc.NSObject { } /// insertValue:inPropertyWithKey: - void insertValue$1( - objc.ObjCObject value, { - required objc.NSString inPropertyWithKey, - }) { + void insertValue$1(objc.ObjCObject value, {required objc.NSString inPropertyWithKey}) { objc.checkOsVersionInternal( 'NSObject.insertValue:inPropertyWithKey:', iOS: (false, (2, 0, 0)), @@ -2875,10 +2593,7 @@ extension NSScriptKeyValueCoding on objc.NSObject { } /// removeValueAtIndex:fromPropertyWithKey: - void removeValueAtIndex( - int index, { - required objc.NSString fromPropertyWithKey, - }) { + void removeValueAtIndex(int index, {required objc.NSString fromPropertyWithKey}) { objc.checkOsVersionInternal( 'NSObject.removeValueAtIndex:fromPropertyWithKey:', iOS: (false, (2, 0, 0)), @@ -2913,10 +2628,7 @@ extension NSScriptKeyValueCoding on objc.NSObject { } /// valueAtIndex:inPropertyWithKey: - objc.ObjCObject? valueAtIndex( - int index, { - required objc.NSString inPropertyWithKey, - }) { + objc.ObjCObject? valueAtIndex(int index, {required objc.NSString inPropertyWithKey}) { objc.checkOsVersionInternal( 'NSObject.valueAtIndex:inPropertyWithKey:', iOS: (false, (2, 0, 0)), @@ -2928,16 +2640,11 @@ extension NSScriptKeyValueCoding on objc.NSObject { index, inPropertyWithKey.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// valueWithName:inPropertyWithKey: - objc.ObjCObject? valueWithName( - objc.NSString name, { - required objc.NSString inPropertyWithKey, - }) { + objc.ObjCObject? valueWithName(objc.NSString name, {required objc.NSString inPropertyWithKey}) { objc.checkOsVersionInternal( 'NSObject.valueWithName:inPropertyWithKey:', iOS: (false, (2, 0, 0)), @@ -2949,9 +2656,7 @@ extension NSScriptKeyValueCoding on objc.NSObject { name.ref.pointer, inPropertyWithKey.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// valueWithUniqueID:inPropertyWithKey: @@ -2970,22 +2675,19 @@ extension NSScriptKeyValueCoding on objc.NSObject { uniqueID.ref.pointer, inPropertyWithKey.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } } late final _sel_objectSpecifier = objc.registerName("objectSpecifier"); -late final _sel_indicesOfObjectsByEvaluatingObjectSpecifier_ = objc - .registerName("indicesOfObjectsByEvaluatingObjectSpecifier:"); +late final _sel_indicesOfObjectsByEvaluatingObjectSpecifier_ = objc.registerName( + "indicesOfObjectsByEvaluatingObjectSpecifier:", +); /// NSScriptObjectSpecifiers extension NSScriptObjectSpecifiers on objc.NSObject { /// indicesOfObjectsByEvaluatingObjectSpecifier: - objc.NSArray? indicesOfObjectsByEvaluatingObjectSpecifier( - NSScriptObjectSpecifier specifier, - ) { + objc.NSArray? indicesOfObjectsByEvaluatingObjectSpecifier(NSScriptObjectSpecifier specifier) { objc.checkOsVersionInternal( 'NSObject.indicesOfObjectsByEvaluatingObjectSpecifier:', iOS: (false, (2, 0, 0)), @@ -2996,9 +2698,7 @@ extension NSScriptObjectSpecifiers on objc.NSObject { _sel_indicesOfObjectsByEvaluatingObjectSpecifier_, specifier.ref.pointer, ); - return $ret.address == 0 - ? null - : objc.NSArray.fromPointer($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.NSArray.fromPointer($ret, retain: true, release: true); } /// objectSpecifier @@ -3008,35 +2708,22 @@ extension NSScriptObjectSpecifiers on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_objectSpecifier, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_objectSpecifier); return $ret.address == 0 ? null - : NSScriptObjectSpecifier.fromPointer( - $ret, - retain: true, - release: true, - ); + : NSScriptObjectSpecifier.fromPointer($ret, retain: true, release: true); } } late final _sel_isEqualTo_ = objc.registerName("isEqualTo:"); -late final _sel_isLessThanOrEqualTo_ = objc.registerName( - "isLessThanOrEqualTo:", -); +late final _sel_isLessThanOrEqualTo_ = objc.registerName("isLessThanOrEqualTo:"); late final _sel_isLessThan_ = objc.registerName("isLessThan:"); -late final _sel_isGreaterThanOrEqualTo_ = objc.registerName( - "isGreaterThanOrEqualTo:", -); +late final _sel_isGreaterThanOrEqualTo_ = objc.registerName("isGreaterThanOrEqualTo:"); late final _sel_isGreaterThan_ = objc.registerName("isGreaterThan:"); late final _sel_isNotEqualTo_ = objc.registerName("isNotEqualTo:"); late final _sel_doesContain_ = objc.registerName("doesContain:"); late final _sel_isLike_ = objc.registerName("isLike:"); -late final _sel_isCaseInsensitiveLike_ = objc.registerName( - "isCaseInsensitiveLike:", -); +late final _sel_isCaseInsensitiveLike_ = objc.registerName("isCaseInsensitiveLike:"); /// NSComparisonMethods extension NSComparisonMethods on objc.NSObject { @@ -3047,11 +2734,7 @@ extension NSComparisonMethods on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_doesContain_, - object.ref.pointer, - ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_doesContain_, object.ref.pointer); } /// isCaseInsensitiveLike: @@ -3145,11 +2828,7 @@ extension NSComparisonMethods on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isLike_, - object.ref.pointer, - ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isLike_, object.ref.pointer); } /// isNotEqualTo: @@ -3168,21 +2847,13 @@ extension NSComparisonMethods on objc.NSObject { } late final _sel_scriptingIsEqualTo_ = objc.registerName("scriptingIsEqualTo:"); -late final _sel_scriptingIsLessThanOrEqualTo_ = objc.registerName( - "scriptingIsLessThanOrEqualTo:", -); -late final _sel_scriptingIsLessThan_ = objc.registerName( - "scriptingIsLessThan:", -); +late final _sel_scriptingIsLessThanOrEqualTo_ = objc.registerName("scriptingIsLessThanOrEqualTo:"); +late final _sel_scriptingIsLessThan_ = objc.registerName("scriptingIsLessThan:"); late final _sel_scriptingIsGreaterThanOrEqualTo_ = objc.registerName( "scriptingIsGreaterThanOrEqualTo:", ); -late final _sel_scriptingIsGreaterThan_ = objc.registerName( - "scriptingIsGreaterThan:", -); -late final _sel_scriptingBeginsWith_ = objc.registerName( - "scriptingBeginsWith:", -); +late final _sel_scriptingIsGreaterThan_ = objc.registerName("scriptingIsGreaterThan:"); +late final _sel_scriptingBeginsWith_ = objc.registerName("scriptingBeginsWith:"); late final _sel_scriptingEndsWith_ = objc.registerName("scriptingEndsWith:"); late final _sel_scriptingContains_ = objc.registerName("scriptingContains:"); @@ -3209,11 +2880,7 @@ extension NSScriptingComparisonMethods on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingContains_, - object.ref.pointer, - ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_scriptingContains_, object.ref.pointer); } /// scriptingEndsWith: @@ -3223,11 +2890,7 @@ extension NSScriptingComparisonMethods on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingEndsWith_, - object.ref.pointer, - ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_scriptingEndsWith_, object.ref.pointer); } /// scriptingIsEqualTo: @@ -3237,11 +2900,7 @@ extension NSScriptingComparisonMethods on objc.NSObject { iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingIsEqualTo_, - object.ref.pointer, - ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_scriptingIsEqualTo_, object.ref.pointer); } /// scriptingIsGreaterThan: @@ -3301,6 +2960,42 @@ extension NSScriptingComparisonMethods on objc.NSObject { } } +enum PHAssetResourceType { + PHAssetResourceTypePhoto(1), + PHAssetResourceTypeVideo(2), + PHAssetResourceTypeAudio(3), + PHAssetResourceTypeAlternatePhoto(4), + PHAssetResourceTypeFullSizePhoto(5), + PHAssetResourceTypeFullSizeVideo(6), + PHAssetResourceTypeAdjustmentData(7), + PHAssetResourceTypeAdjustmentBasePhoto(8), + PHAssetResourceTypePairedVideo(9), + PHAssetResourceTypeFullSizePairedVideo(10), + PHAssetResourceTypeAdjustmentBasePairedVideo(11), + PHAssetResourceTypeAdjustmentBaseVideo(12), + PHAssetResourceTypePhotoProxy(19); + + final int value; + const PHAssetResourceType(this.value); + + static PHAssetResourceType fromValue(int value) => switch (value) { + 1 => PHAssetResourceTypePhoto, + 2 => PHAssetResourceTypeVideo, + 3 => PHAssetResourceTypeAudio, + 4 => PHAssetResourceTypeAlternatePhoto, + 5 => PHAssetResourceTypeFullSizePhoto, + 6 => PHAssetResourceTypeFullSizeVideo, + 7 => PHAssetResourceTypeAdjustmentData, + 8 => PHAssetResourceTypeAdjustmentBasePhoto, + 9 => PHAssetResourceTypePairedVideo, + 10 => PHAssetResourceTypeFullSizePairedVideo, + 11 => PHAssetResourceTypeAdjustmentBasePairedVideo, + 12 => PHAssetResourceTypeAdjustmentBaseVideo, + 19 => PHAssetResourceTypePhotoProxy, + _ => throw ArgumentError('Unknown value for PHAssetResourceType: $value'), + }; +} + late final _class_PHObject = objc.getClass("PHObject"); /// PHObject @@ -3308,11 +3003,7 @@ extension type PHObject._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject, objc.NSCopying { /// Constructs a [PHObject] that points to the same underlying object as [other]. PHObject.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHObject', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); + objc.checkOsVersionInternal('PHObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); assert(isA(object$)); } @@ -3322,20 +3013,13 @@ extension type PHObject._(objc.ObjCObject object$) bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHObject', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); + objc.checkOsVersionInternal('PHObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); assert(isA(object$)); } /// Returns whether [obj] is an instance of [PHObject]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHObject, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHObject); } extension PHObject$Methods on PHObject {} @@ -3345,11 +3029,7 @@ late final _sel_firstObject = objc.registerName("firstObject"); /// PHFetchResult extension type PHFetchResult._(objc.ObjCObject object$) - implements - objc.ObjCObject, - objc.NSObject, - objc.NSCopying, - objc.NSFastEnumeration { + implements objc.ObjCObject, objc.NSObject, objc.NSCopying, objc.NSFastEnumeration { /// Constructs a [PHFetchResult] that points to the same underlying object as [other]. PHFetchResult.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( @@ -3375,11 +3055,8 @@ extension type PHFetchResult._(objc.ObjCObject object$) } /// Returns whether [obj] is an instance of [PHFetchResult]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHFetchResult, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHFetchResult); } extension PHFetchResult$Methods on PHFetchResult { @@ -3391,9 +3068,7 @@ extension PHFetchResult$Methods on PHFetchResult { macOS: (false, (10, 13, 0)), ); final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_firstObject); - return $ret.address == 0 - ? null - : objc.ObjCObject($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } } @@ -3419,9 +3094,7 @@ enum CGImagePropertyOrientation { 6 => kCGImagePropertyOrientationRight, 7 => kCGImagePropertyOrientationRightMirrored, 8 => kCGImagePropertyOrientationLeft, - _ => throw ArgumentError( - 'Unknown value for CGImagePropertyOrientation: $value', - ), + _ => throw ArgumentError('Unknown value for CGImagePropertyOrientation: $value'), }; } @@ -3468,8 +3141,7 @@ late final _sel_fetchAssetsWithLocalIdentifiers_options_ = objc.registerName( extension type PHContentEditingInputRequestOptions._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { /// Constructs a [PHContentEditingInputRequestOptions] that points to the same underlying object as [other]. - PHContentEditingInputRequestOptions.as(objc.ObjCObject other) - : object$ = other { + PHContentEditingInputRequestOptions.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( 'PHContentEditingInputRequestOptions', iOS: (false, (8, 0, 0)), @@ -3523,26 +3195,22 @@ extension type PHContentEditingInput._(objc.ObjCObject object$) /// Construction methods for `objc.ObjCBlock`. abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > - fromPointer( + static objc.ObjCBlock fromPointer( ffi.Pointer pointer, { bool retain = false, bool release = false, - }) => - objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - >(pointer, retain: retain, release: release); + }) => objc.ObjCBlock( + pointer, + retain: retain, + release: release, + ); /// Creates a block from a C function pointer. /// /// This block must be invoked by native code running on the same thread as /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. - static objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > + static objc.ObjCBlock fromFunctionPointer( ffi.Pointer< ffi.NativeFunction< @@ -3553,14 +3221,11 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { > > ptr, - ) => - objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - >( - objc.newPointerBlock(_fnPtrCallable, ptr.cast()), - retain: false, - release: true, - ); + ) => objc.ObjCBlock( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); /// Creates a block from a Dart function. /// @@ -3570,36 +3235,23 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > - fromFunction( + static objc.ObjCBlock fromFunction( void Function(PHContentEditingInput?, objc.NSDictionary) fn, { bool keepIsolateAlive = true, - }) => - objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - >( - objc.newClosureBlock( - _closureCallable, - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - ) => fn( - arg0.address == 0 - ? null - : PHContentEditingInput.fromPointer( - arg0, - retain: true, - release: true, - ), - objc.NSDictionary.fromPointer(arg1, retain: true, release: true), - ), - keepIsolateAlive, - ), - retain: false, - release: true, - ); + }) => objc.ObjCBlock( + objc.newClosureBlock( + _closureCallable, + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( + arg0.address == 0 + ? null + : PHContentEditingInput.fromPointer(arg0, retain: true, release: true), + objc.NSDictionary.fromPointer(arg1, retain: true, release: true), + ), + keepIsolateAlive, + ), + retain: false, + release: true, + ); /// Creates a listener block from a Dart function. /// @@ -3610,35 +3262,27 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > - listener( + static objc.ObjCBlock listener( void Function(PHContentEditingInput?, objc.NSDictionary) fn, { bool keepIsolateAlive = true, }) { final raw = objc.newClosureBlock( _listenerCallable.nativeFunction.cast(), - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - ) => fn( + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( arg0.address == 0 ? null - : PHContentEditingInput.fromPointer( - arg0, - retain: false, - release: true, - ), + : PHContentEditingInput.fromPointer(arg0, retain: false, release: true), objc.NSDictionary.fromPointer(arg1, retain: false, release: true), ), keepIsolateAlive, ); final wrapper = _NativeLibrary_wrapListenerBlock_pfv6jd(raw); objc.objectRelease(raw.cast()); - return objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - >(wrapper, retain: false, release: true); + return objc.ObjCBlock( + wrapper, + retain: false, + release: true, + ); } /// Creates a blocking block from a Dart function. @@ -3651,57 +3295,38 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// until it is garbage collected by both Dart and ObjC. If the owner isolate /// has shut down, and the block is invoked by native code, it may block /// indefinitely, or have other undefined behavior. - static objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > - blocking( + static objc.ObjCBlock blocking( void Function(PHContentEditingInput?, objc.NSDictionary) fn, { bool keepIsolateAlive = true, }) { final raw = objc.newClosureBlock( _blockingCallable.nativeFunction.cast(), - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - ) => fn( + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( arg0.address == 0 ? null - : PHContentEditingInput.fromPointer( - arg0, - retain: false, - release: true, - ), + : PHContentEditingInput.fromPointer(arg0, retain: false, release: true), objc.NSDictionary.fromPointer(arg1, retain: false, release: true), ), keepIsolateAlive, ); final rawListener = objc.newClosureBlock( _blockingListenerCallable.nativeFunction.cast(), - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - ) => fn( + (ffi.Pointer arg0, ffi.Pointer arg1) => fn( arg0.address == 0 ? null - : PHContentEditingInput.fromPointer( - arg0, - retain: false, - release: true, - ), + : PHContentEditingInput.fromPointer(arg0, retain: false, release: true), objc.NSDictionary.fromPointer(arg1, retain: false, release: true), ), keepIsolateAlive, ); - final wrapper = _NativeLibrary_wrapBlockingBlock_pfv6jd( - raw, - rawListener, - objc.objCContext, - ); + final wrapper = _NativeLibrary_wrapBlockingBlock_pfv6jd(raw, rawListener, objc.objCContext); objc.objectRelease(raw.cast()); objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - >(wrapper, retain: false, release: true); + return objc.ObjCBlock( + wrapper, + retain: false, + release: true, + ); } static void _listenerTrampoline( @@ -3710,10 +3335,10 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { ffi.Pointer arg1, ) { (objc.getBlockClosure(block) - as void Function( - ffi.Pointer, - ffi.Pointer, - ))(arg0, arg1); + as void Function(ffi.Pointer, ffi.Pointer))( + arg0, + arg1, + ); objc.objectRelease(block.cast()); } @@ -3741,10 +3366,10 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { ) { try { (objc.getBlockClosure(block) - as void Function( - ffi.Pointer, - ffi.Pointer, - ))(arg0, arg1); + as void Function(ffi.Pointer, ffi.Pointer))( + arg0, + arg1, + ); } catch (e) { } finally { objc.signalWaiter(waiter); @@ -3802,10 +3427,7 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { > >() .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ) + void Function(ffi.Pointer, ffi.Pointer) >()(arg0, arg1); static ffi.Pointer _fnPtrCallable = ffi.Pointer.fromFunction< @@ -3822,10 +3444,10 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { ffi.Pointer arg1, ) => (objc.getBlockClosure(block) - as void Function( - ffi.Pointer, - ffi.Pointer, - ))(arg0, arg1); + as void Function(ffi.Pointer, ffi.Pointer))( + arg0, + arg1, + ); static ffi.Pointer _closureCallable = ffi.Pointer.fromFunction< ffi.Void Function( @@ -3839,14 +3461,8 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// Call operator for `objc.ObjCBlock`. extension ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary$CallExtension - on - objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > { - void call(PHContentEditingInput? arg0, objc.NSDictionary arg1) => ref - .pointer - .ref - .invoke + on objc.ObjCBlock { + void call(PHContentEditingInput? arg0, objc.NSDictionary arg1) => ref.pointer.ref.invoke .cast< ffi.NativeFunction< ffi.Void Function( @@ -3865,8 +3481,9 @@ extension ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary$CallExtension >()(ref.pointer, arg0?.ref.pointer ?? ffi.nullptr, arg1.ref.pointer); } -late final _sel_requestContentEditingInputWithOptions_completionHandler_ = objc - .registerName("requestContentEditingInputWithOptions:completionHandler:"); +late final _sel_requestContentEditingInputWithOptions_completionHandler_ = objc.registerName( + "requestContentEditingInputWithOptions:completionHandler:", +); final _objc_msgSend_jkkt9d = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -3900,11 +3517,7 @@ final _objc_msgSend_1i9r4xy = objc.msgSendPointer > >() .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - int, - ) + void Function(ffi.Pointer, ffi.Pointer, int) >(); /// PHContentEditingInput @@ -3916,19 +3529,13 @@ extension PHContentEditingInput$1 on PHAsset { iOS: (false, (8, 0, 0)), macOS: (false, (10, 15, 0)), ); - _objc_msgSend_1i9r4xy( - object$.ref.pointer, - _sel_cancelContentEditingInputRequest_, - requestID, - ); + _objc_msgSend_1i9r4xy(object$.ref.pointer, _sel_cancelContentEditingInputRequest_, requestID); } /// requestContentEditingInputWithOptions:completionHandler: int requestContentEditingInputWithOptions( PHContentEditingInputRequestOptions? options, { - required objc.ObjCBlock< - ffi.Void Function(PHContentEditingInput?, objc.NSDictionary) - > + required objc.ObjCBlock completionHandler, }) { objc.checkOsVersionInternal( @@ -3946,15 +3553,10 @@ extension PHContentEditingInput$1 on PHAsset { } /// PHAsset -extension type PHAsset._(objc.ObjCObject object$) - implements objc.ObjCObject, PHObject { +extension type PHAsset._(objc.ObjCObject object$) implements objc.ObjCObject, PHObject { /// Constructs a [PHAsset] that points to the same underlying object as [other]. PHAsset.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHAsset', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); + objc.checkOsVersionInternal('PHAsset', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); assert(isA(object$)); } @@ -3964,20 +3566,13 @@ extension type PHAsset._(objc.ObjCObject object$) bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHAsset', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); + objc.checkOsVersionInternal('PHAsset', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); assert(isA(object$)); } /// Returns whether [obj] is an instance of [PHAsset]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHAsset, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAsset); /// fetchAssetsWithLocalIdentifiers:options: static PHFetchResult fetchAssetsWithLocalIdentifiers( @@ -4007,18 +3602,14 @@ extension PHAsset$Methods on PHAsset { iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_modificationDate, - ); - return $ret.address == 0 - ? null - : objc.NSDate.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_modificationDate); + return $ret.address == 0 ? null : objc.NSDate.fromPointer($ret, retain: true, release: true); } } -late final _sel_provideImageData_bytesPerRow_origin__size__userInfo_ = objc - .registerName("provideImageData:bytesPerRow:origin::size::userInfo:"); +late final _sel_provideImageData_bytesPerRow_origin__size__userInfo_ = objc.registerName( + "provideImageData:bytesPerRow:origin::size::userInfo:", +); final _objc_msgSend_haq63t = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -4053,8 +3644,7 @@ final _objc_msgSend_haq63t = objc.msgSendPointer /// MTLTexture in your config's objc-protocols list. /// /// MTLTexture -extension type MTLTexture._(objc.ObjCProtocol object$) - implements objc.ObjCProtocol { +extension type MTLTexture._(objc.ObjCProtocol object$) implements objc.ObjCProtocol { /// Constructs a [MTLTexture] that points to the same underlying object as [other]. MTLTexture.as(objc.ObjCObject other) : object$ = other; @@ -4070,8 +3660,7 @@ extension type MTLTexture._(objc.ObjCProtocol object$) /// MTLCommandBuffer in your config's objc-protocols list. /// /// MTLCommandBuffer -extension type MTLCommandBuffer._(objc.ObjCProtocol object$) - implements objc.ObjCProtocol { +extension type MTLCommandBuffer._(objc.ObjCProtocol object$) implements objc.ObjCProtocol { /// Constructs a [MTLCommandBuffer] that points to the same underlying object as [other]. MTLCommandBuffer.as(objc.ObjCObject other) : object$ = other; @@ -4083,10 +3672,8 @@ extension type MTLCommandBuffer._(objc.ObjCProtocol object$) }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); } -late final _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_ = - objc.registerName( - "provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:", - ); +late final _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_ = objc + .registerName("provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:"); final _objc_msgSend_1jjfka7 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -4175,12 +3762,8 @@ extension CIImageProvider on objc.NSObject { } } -late final _class_PHImageRequestOptions = objc.getClass( - "PHImageRequestOptions", -); -late final _sel_setNetworkAccessAllowed_ = objc.registerName( - "setNetworkAccessAllowed:", -); +late final _class_PHImageRequestOptions = objc.getClass("PHImageRequestOptions"); +late final _sel_setNetworkAccessAllowed_ = objc.registerName("setNetworkAccessAllowed:"); final _objc_msgSend_1s56lr9 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -4192,11 +3775,7 @@ final _objc_msgSend_1s56lr9 = objc.msgSendPointer > >() .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - bool, - ) + void Function(ffi.Pointer, ffi.Pointer, bool) >(); typedef instancetype = ffi.Pointer; typedef Dartinstancetype = objc.ObjCObject; @@ -4230,20 +3809,13 @@ extension type PHImageRequestOptions._(objc.ObjCObject object$) } /// Returns whether [obj] is an instance of [PHImageRequestOptions]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHImageRequestOptions, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHImageRequestOptions); /// new static PHImageRequestOptions new$() { final $ret = _objc_msgSend_151sglz(_class_PHImageRequestOptions, _sel_new); - return PHImageRequestOptions.fromPointer( - $ret, - retain: false, - release: true, - ); + return PHImageRequestOptions.fromPointer($ret, retain: false, release: true); } /// Returns a new instance of PHImageRequestOptions constructed with the default `new` method. @@ -4258,11 +3830,7 @@ extension PHImageRequestOptions$Methods on PHImageRequestOptions { iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - _objc_msgSend_1s56lr9( - object$.ref.pointer, - _sel_setNetworkAccessAllowed_, - value, - ); + _objc_msgSend_1s56lr9(object$.ref.pointer, _sel_setNetworkAccessAllowed_, value); } } @@ -4272,12 +3840,7 @@ late final _class_PHImageManager = objc.getClass("PHImageManager"); abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary { /// Returns a block that wraps the given raw block pointer. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > fromPointer( ffi.Pointer pointer, { @@ -4285,12 +3848,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio bool release = false, }) => objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) >(pointer, retain: retain, release: release); /// Creates a block from a C function pointer. @@ -4299,12 +3857,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > fromFunctionPointer( ffi.Pointer< @@ -4320,17 +3873,8 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ptr, ) => objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) - >( - objc.newPointerBlock(_fnPtrCallable, ptr.cast()), - retain: false, - release: true, - ); + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + >(objc.newPointerBlock(_fnPtrCallable, ptr.cast()), retain: false, release: true); /// Creates a block from a Dart function. /// @@ -4341,30 +3885,15 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > fromFunction( - void Function( - objc.NSData?, - objc.NSString?, - CGImagePropertyOrientation, - objc.NSDictionary?, - ) + void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) fn, { bool keepIsolateAlive = true, }) => objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) >( objc.newClosureBlock( _closureCallable, @@ -4374,20 +3903,12 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio int arg2, ffi.Pointer arg3, ) => fn( - arg0.address == 0 - ? null - : objc.NSData.fromPointer(arg0, retain: true, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: true, release: true), + arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: true, release: true), + arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: true, release: true), CGImagePropertyOrientation.fromValue(arg2), arg3.address == 0 ? null - : objc.NSDictionary.fromPointer( - arg3, - retain: true, - release: true, - ), + : objc.NSDictionary.fromPointer(arg3, retain: true, release: true), ), keepIsolateAlive, ), @@ -4405,20 +3926,10 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > listener( - void Function( - objc.NSData?, - objc.NSString?, - CGImagePropertyOrientation, - objc.NSDictionary?, - ) + void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) fn, { bool keepIsolateAlive = true, }) { @@ -4430,12 +3941,8 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio int arg2, ffi.Pointer arg3, ) => fn( - arg0.address == 0 - ? null - : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: false, release: true), + arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: false, release: true), CGImagePropertyOrientation.fromValue(arg2), arg3.address == 0 ? null @@ -4446,12 +3953,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio final wrapper = _NativeLibrary_wrapListenerBlock_10c3wkj(raw); objc.objectRelease(raw.cast()); return objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) >(wrapper, retain: false, release: true); } @@ -4466,20 +3968,10 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio /// has shut down, and the block is invoked by native code, it may block /// indefinitely, or have other undefined behavior. static objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > blocking( - void Function( - objc.NSData?, - objc.NSString?, - CGImagePropertyOrientation, - objc.NSDictionary?, - ) + void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) fn, { bool keepIsolateAlive = true, }) { @@ -4491,12 +3983,8 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio int arg2, ffi.Pointer arg3, ) => fn( - arg0.address == 0 - ? null - : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: false, release: true), + arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: false, release: true), CGImagePropertyOrientation.fromValue(arg2), arg3.address == 0 ? null @@ -4512,12 +4000,8 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio int arg2, ffi.Pointer arg3, ) => fn( - arg0.address == 0 - ? null - : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 - ? null - : objc.NSString.fromPointer(arg1, retain: false, release: true), + arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: false, release: true), + arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: false, release: true), CGImagePropertyOrientation.fromValue(arg2), arg3.address == 0 ? null @@ -4525,20 +4009,11 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio ), keepIsolateAlive, ); - final wrapper = _NativeLibrary_wrapBlockingBlock_10c3wkj( - raw, - rawListener, - objc.objCContext, - ); + final wrapper = _NativeLibrary_wrapBlockingBlock_10c3wkj(raw, rawListener, objc.objCContext); objc.objectRelease(raw.cast()); objc.objectRelease(rawListener.cast()); return objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) >(wrapper, retain: false, release: true); } @@ -4713,12 +4188,7 @@ abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientatio extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary$CallExtension on objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > { void call( objc.NSData? arg0, @@ -4755,10 +4225,9 @@ extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDiction ); } -late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = - objc.registerName( - "requestImageDataAndOrientationForAsset:options:resultHandler:", - ); +late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = objc.registerName( + "requestImageDataAndOrientationForAsset:options:resultHandler:", +); final _objc_msgSend_1urj8nv = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -4782,8 +4251,7 @@ final _objc_msgSend_1urj8nv = objc.msgSendPointer >(); /// PHImageManager -extension type PHImageManager._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { +extension type PHImageManager._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { /// Constructs a [PHImageManager] that points to the same underlying object as [other]. PHImageManager.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( @@ -4809,11 +4277,8 @@ extension type PHImageManager._(objc.ObjCObject object$) } /// Returns whether [obj] is an instance of [PHImageManager]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHImageManager, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHImageManager); /// defaultManager static PHImageManager defaultManager() { @@ -4822,10 +4287,7 @@ extension type PHImageManager._(objc.ObjCObject object$) iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - final $ret = _objc_msgSend_151sglz( - _class_PHImageManager, - _sel_defaultManager, - ); + final $ret = _objc_msgSend_151sglz(_class_PHImageManager, _sel_defaultManager); return PHImageManager.fromPointer($ret, retain: true, release: true); } } @@ -4836,12 +4298,7 @@ extension PHImageManager$Methods on PHImageManager { PHAsset asset, { PHImageRequestOptions? options, required objc.ObjCBlock< - ffi.Void Function( - objc.NSData?, - objc.NSString?, - ffi.Uint32, - objc.NSDictionary?, - ) + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) > resultHandler, }) { @@ -4889,14 +4346,18 @@ extension type PHAssetResourceRequestOptions._(objc.ObjCObject object$) } } -late final _class_PHAssetResourceManager = objc.getClass( - "PHAssetResourceManager", -); +late final _class_PHAssetResourceManager = objc.getClass("PHAssetResourceManager"); late final _class_PHAssetResource = objc.getClass("PHAssetResource"); +late final _sel_type = objc.registerName("type"); +final _objc_msgSend_1or4ucj = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Long Function(ffi.Pointer, ffi.Pointer) + > + >() + .asFunction, ffi.Pointer)>(); late final _sel_originalFilename = objc.registerName("originalFilename"); -late final _sel_assetResourcesForAsset_ = objc.registerName( - "assetResourcesForAsset:", -); +late final _sel_assetResourcesForAsset_ = objc.registerName("assetResourcesForAsset:"); /// PHAssetResource extension type PHAssetResource._(objc.ObjCObject object$) @@ -4926,11 +4387,8 @@ extension type PHAssetResource._(objc.ObjCObject object$) } /// Returns whether [obj] is an instance of [PHAssetResource]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHAssetResource, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAssetResource); /// assetResourcesForAsset: static objc.NSArray assetResourcesForAsset(PHAsset asset) { @@ -4956,12 +4414,20 @@ extension PHAssetResource$Methods on PHAssetResource { iOS: (false, (9, 0, 0)), macOS: (false, (10, 15, 0)), ); - final $ret = _objc_msgSend_151sglz( - object$.ref.pointer, - _sel_originalFilename, - ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_originalFilename); return objc.NSString.fromPointer($ret, retain: true, release: true); } + + /// type + PHAssetResourceType get type { + objc.checkOsVersionInternal( + 'PHAssetResource.type', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + final $ret = _objc_msgSend_1or4ucj(object$.ref.pointer, _sel_type); + return PHAssetResourceType.fromValue($ret); + } } /// Construction methods for `objc.ObjCBlock`. @@ -4971,11 +4437,7 @@ abstract final class ObjCBlock_ffiVoid_NSData { ffi.Pointer pointer, { bool retain = false, bool release = false, - }) => objc.ObjCBlock( - pointer, - retain: retain, - release: release, - ); + }) => objc.ObjCBlock(pointer, retain: retain, release: release); /// Creates a block from a C function pointer. /// @@ -4983,12 +4445,7 @@ abstract final class ObjCBlock_ffiVoid_NSData { /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. static objc.ObjCBlock fromFunctionPointer( - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer arg0) - > - > - ptr, + ffi.Pointer arg0)>> ptr, ) => objc.ObjCBlock( objc.newPointerBlock(_fnPtrCallable, ptr.cast()), retain: false, @@ -5038,11 +4495,7 @@ abstract final class ObjCBlock_ffiVoid_NSData { ); final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw); objc.objectRelease(raw.cast()); - return objc.ObjCBlock( - wrapper, - retain: false, - release: true, - ); + return objc.ObjCBlock(wrapper, retain: false, release: true); } /// Creates a blocking block from a Dart function. @@ -5071,41 +4524,26 @@ abstract final class ObjCBlock_ffiVoid_NSData { fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), keepIsolateAlive, ); - final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7( - raw, - rawListener, - objc.objCContext, - ); + final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7(raw, rawListener, objc.objCContext); objc.objectRelease(raw.cast()); objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock( - wrapper, - retain: false, - release: true, - ); + return objc.ObjCBlock(wrapper, retain: false, release: true); } static void _listenerTrampoline( ffi.Pointer block, ffi.Pointer arg0, ) { - (objc.getBlockClosure(block) - as void Function(ffi.Pointer))(arg0); + (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); objc.objectRelease(block.cast()); } static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) > _listenerCallable = ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) >.listener(_listenerTrampoline) ..keepIsolateAlive = false; static void _blockingTrampoline( @@ -5114,8 +4552,7 @@ abstract final class ObjCBlock_ffiVoid_NSData { ffi.Pointer arg0, ) { try { - (objc.getBlockClosure(block) - as void Function(ffi.Pointer))(arg0); + (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); } catch (e) { } finally { objc.signalWaiter(waiter); @@ -5159,39 +4596,26 @@ abstract final class ObjCBlock_ffiVoid_NSData { ffi.Pointer block, ffi.Pointer arg0, ) => block.ref.target - .cast< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer arg0) - > - >() + .cast arg0)>>() .asFunction)>()(arg0); static ffi.Pointer _fnPtrCallable = ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) >(_fnPtrTrampoline) .cast(); static void _closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, - ) => - (objc.getBlockClosure(block) - as void Function(ffi.Pointer))(arg0); + ) => (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); static ffi.Pointer _closureCallable = ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) >(_closureTrampoline) .cast(); } /// Call operator for `objc.ObjCBlock`. -extension ObjCBlock_ffiVoid_NSData$CallExtension - on objc.ObjCBlock { +extension ObjCBlock_ffiVoid_NSData$CallExtension on objc.ObjCBlock { void call(objc.NSData arg0) => ref.pointer.ref.invoke .cast< ffi.NativeFunction< @@ -5202,10 +4626,7 @@ extension ObjCBlock_ffiVoid_NSData$CallExtension > >() .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ) + void Function(ffi.Pointer, ffi.Pointer) >()(ref.pointer, arg0.ref.pointer); } @@ -5216,11 +4637,7 @@ abstract final class ObjCBlock_ffiVoid_NSError { ffi.Pointer pointer, { bool retain = false, bool release = false, - }) => objc.ObjCBlock( - pointer, - retain: retain, - release: release, - ); + }) => objc.ObjCBlock(pointer, retain: retain, release: release); /// Creates a block from a C function pointer. /// @@ -5228,12 +4645,7 @@ abstract final class ObjCBlock_ffiVoid_NSError { /// the isolate that registered it. Invoking the block on the wrong thread /// will result in a crash. static objc.ObjCBlock fromFunctionPointer( - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer arg0) - > - > - ptr, + ffi.Pointer arg0)>> ptr, ) => objc.ObjCBlock( objc.newPointerBlock(_fnPtrCallable, ptr.cast()), retain: false, @@ -5255,9 +4667,7 @@ abstract final class ObjCBlock_ffiVoid_NSError { objc.newClosureBlock( _closureCallable, (ffi.Pointer arg0) => fn( - arg0.address == 0 - ? null - : objc.NSError.fromPointer(arg0, retain: true, release: true), + arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: true, release: true), ), keepIsolateAlive, ), @@ -5281,19 +4691,13 @@ abstract final class ObjCBlock_ffiVoid_NSError { final raw = objc.newClosureBlock( _listenerCallable.nativeFunction.cast(), (ffi.Pointer arg0) => fn( - arg0.address == 0 - ? null - : objc.NSError.fromPointer(arg0, retain: false, release: true), + arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true), ), keepIsolateAlive, ); final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw); objc.objectRelease(raw.cast()); - return objc.ObjCBlock( - wrapper, - retain: false, - release: true, - ); + return objc.ObjCBlock(wrapper, retain: false, release: true); } /// Creates a blocking block from a Dart function. @@ -5313,56 +4717,37 @@ abstract final class ObjCBlock_ffiVoid_NSError { final raw = objc.newClosureBlock( _blockingCallable.nativeFunction.cast(), (ffi.Pointer arg0) => fn( - arg0.address == 0 - ? null - : objc.NSError.fromPointer(arg0, retain: false, release: true), + arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true), ), keepIsolateAlive, ); final rawListener = objc.newClosureBlock( _blockingListenerCallable.nativeFunction.cast(), (ffi.Pointer arg0) => fn( - arg0.address == 0 - ? null - : objc.NSError.fromPointer(arg0, retain: false, release: true), + arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true), ), keepIsolateAlive, ); - final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7( - raw, - rawListener, - objc.objCContext, - ); + final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7(raw, rawListener, objc.objCContext); objc.objectRelease(raw.cast()); objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock( - wrapper, - retain: false, - release: true, - ); + return objc.ObjCBlock(wrapper, retain: false, release: true); } static void _listenerTrampoline( ffi.Pointer block, ffi.Pointer arg0, ) { - (objc.getBlockClosure(block) - as void Function(ffi.Pointer))(arg0); + (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); objc.objectRelease(block.cast()); } static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) > _listenerCallable = ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) >.listener(_listenerTrampoline) ..keepIsolateAlive = false; static void _blockingTrampoline( @@ -5371,8 +4756,7 @@ abstract final class ObjCBlock_ffiVoid_NSError { ffi.Pointer arg0, ) { try { - (objc.getBlockClosure(block) - as void Function(ffi.Pointer))(arg0); + (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); } catch (e) { } finally { objc.signalWaiter(waiter); @@ -5416,32 +4800,20 @@ abstract final class ObjCBlock_ffiVoid_NSError { ffi.Pointer block, ffi.Pointer arg0, ) => block.ref.target - .cast< - ffi.NativeFunction< - ffi.Void Function(ffi.Pointer arg0) - > - >() + .cast arg0)>>() .asFunction)>()(arg0); static ffi.Pointer _fnPtrCallable = ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) >(_fnPtrTrampoline) .cast(); static void _closureTrampoline( ffi.Pointer block, ffi.Pointer arg0, - ) => - (objc.getBlockClosure(block) - as void Function(ffi.Pointer))(arg0); + ) => (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); static ffi.Pointer _closureCallable = ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ) + ffi.Void Function(ffi.Pointer, ffi.Pointer) >(_closureTrampoline) .cast(); } @@ -5459,17 +4831,12 @@ extension ObjCBlock_ffiVoid_NSError$CallExtension > >() .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ) + void Function(ffi.Pointer, ffi.Pointer) >()(ref.pointer, arg0?.ref.pointer ?? ffi.nullptr); } -late final _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_ = - objc.registerName( - "requestDataForAssetResource:options:dataReceivedHandler:completionHandler:", - ); +late final _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_ = objc + .registerName("requestDataForAssetResource:options:dataReceivedHandler:completionHandler:"); final _objc_msgSend_p4k360 = objc.msgSendPointer .cast< ffi.NativeFunction< @@ -5522,11 +4889,8 @@ extension type PHAssetResourceManager._(objc.ObjCObject object$) } /// Returns whether [obj] is an instance of [PHAssetResourceManager]. - static bool isA(objc.ObjCObject obj) => _objc_msgSend_19nvye5( - obj.ref.pointer, - _sel_isKindOfClass_, - _class_PHAssetResourceManager, - ); + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAssetResourceManager); /// defaultManager static PHAssetResourceManager defaultManager() { @@ -5535,15 +4899,8 @@ extension type PHAssetResourceManager._(objc.ObjCObject object$) iOS: (false, (9, 0, 0)), macOS: (false, (10, 15, 0)), ); - final $ret = _objc_msgSend_151sglz( - _class_PHAssetResourceManager, - _sel_defaultManager, - ); - return PHAssetResourceManager.fromPointer( - $ret, - retain: true, - release: true, - ); + final $ret = _objc_msgSend_151sglz(_class_PHAssetResourceManager, _sel_defaultManager); + return PHAssetResourceManager.fromPointer($ret, retain: true, release: true); } } diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 15202f47f0f4..6fcd1b9250ba 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -26,6 +26,7 @@ void main() { objectiveC: ObjectiveC( interfaces: Interfaces( include: (Declaration declaration) { + print('Apple: ${declaration.originalName}'); return { 'NSFileManager', 'NSObject', @@ -38,9 +39,6 @@ void main() { }.contains(declaration.originalName); }, includeMember: (Declaration declaration, String member) { - if (declaration.originalName == 'PHImageRequestOptions') { - print('Apple: $member'); - } final String interfaceName = declaration.originalName; final signature = member; return switch (interfaceName) { @@ -56,6 +54,7 @@ void main() { 'PHAssetResource' => { 'assetResourcesForAsset:', 'originalFilename', + 'type', }.contains(signature), 'PHAssetResourceManager' => { 'defaultManager', @@ -74,6 +73,7 @@ void main() { }; }, ), + ), ).generate(); } From f31376976587fbc7d5c18409b5e190fb4201853f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:44:39 -0400 Subject: [PATCH 285/398] better prints --- .../lib/src/darwin_scoped_storage_cross_file.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 74b3706fef78..d1ce3361f5fd 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -217,8 +217,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile if (end == null) { if (currentByteIndex >= startOrZero) { - print('add'); - print(bytes.length); + print('adding ${bytes.length} bytes. starting with ${bytes[0]} ${bytes[1]}'); streamController.add(bytes); } else { if (newByteIndex > startOrZero) { @@ -255,6 +254,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile streamController.addError(Exception(error.localizedDescription.toDartString())); } + print('end stream'); return streamController.close(); }); } From 99016fe7aa2379c8afcb1c112bbc5cc220154a97 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:50:08 -0400 Subject: [PATCH 286/398] add contentType g --- .../src/darwin_scoped_storage_cross_file.dart | 1 + .../lib/src/ffi_bindings.g.dart | 220 ++++++++++++++++++ .../cross_file_darwin/tool/ffigen.dart | 8 +- 3 files changed, 225 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index d1ce3361f5fd..cd7ffb3d251a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -346,6 +346,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile for (var index = 0; index < resources.count; index++) { final resource = PHAssetResource.as(resources.objectAtIndex(index)); print('cfd: ${resource.type}'); + print('cfd: ${resource.contentType.preferredMIMEType}'); } if (firstObject != null) { diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 2c24548865d1..935780ddbe11 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -3607,6 +3607,214 @@ extension PHAsset$Methods on PHAsset { } } +late final _class_UTType = objc.getClass("UTType"); +late final _sel_preferredMIMEType = objc.registerName("preferredMIMEType"); +late final _sel_conformsToType_ = objc.registerName("conformsToType:"); +late final _sel_isSupertypeOfType_ = objc.registerName("isSupertypeOfType:"); +late final _sel_isSubtypeOfType_ = objc.registerName("isSubtypeOfType:"); +late final _sel_supertypes = objc.registerName("supertypes"); + +/// Conformance +extension Conformance on UTType { + /// conformsToType: + bool conformsToType(UTType type) { + objc.checkOsVersionInternal( + 'UTType.conformsToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_conformsToType_, type.ref.pointer); + } + + /// isSubtypeOfType: + bool isSubtypeOfType(UTType type) { + objc.checkOsVersionInternal( + 'UTType.isSubtypeOfType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isSubtypeOfType_, type.ref.pointer); + } + + /// isSupertypeOfType: + bool isSupertypeOfType(UTType type) { + objc.checkOsVersionInternal( + 'UTType.isSupertypeOfType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isSupertypeOfType_, type.ref.pointer); + } + + /// supertypes + objc.NSSet get supertypes { + objc.checkOsVersionInternal( + 'UTType.supertypes', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_supertypes); + return objc.NSSet.fromPointer($ret, retain: true, release: true); + } +} + +late final _sel_typesWithTag_tagClass_conformingToType_ = objc.registerName( + "typesWithTag:tagClass:conformingToType:", +); +late final _sel_tags = objc.registerName("tags"); + +/// UTTagSpecification +extension UTTagSpecification on UTType { + /// tags + objc.NSDictionary get tags { + objc.checkOsVersionInternal( + 'UTType.tags', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_tags); + return objc.NSDictionary.fromPointer($ret, retain: true, release: true); + } + + /// typesWithTag:tagClass:conformingToType: + static objc.NSArray typesWithTag( + objc.NSString tag, { + required objc.NSString tagClass, + UTType? conformingToType, + }) { + objc.checkOsVersionInternal( + 'UTType.typesWithTag:tagClass:conformingToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_11spmsz( + _class_UTType, + _sel_typesWithTag_tagClass_conformingToType_, + tag.ref.pointer, + tagClass.ref.pointer, + conformingToType?.ref.pointer ?? ffi.nullptr, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } +} + +late final _sel_exportedTypeWithIdentifier_ = objc.registerName("exportedTypeWithIdentifier:"); +late final _sel_exportedTypeWithIdentifier_conformingToType_ = objc.registerName( + "exportedTypeWithIdentifier:conformingToType:", +); +late final _sel_importedTypeWithIdentifier_ = objc.registerName("importedTypeWithIdentifier:"); +late final _sel_importedTypeWithIdentifier_conformingToType_ = objc.registerName( + "importedTypeWithIdentifier:conformingToType:", +); + +/// LocalConstants +extension LocalConstants on UTType { + /// exportedTypeWithIdentifier: + static UTType exportedTypeWithIdentifier(objc.NSString identifier) { + objc.checkOsVersionInternal( + 'UTType.exportedTypeWithIdentifier:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _class_UTType, + _sel_exportedTypeWithIdentifier_, + identifier.ref.pointer, + ); + return UTType.fromPointer($ret, retain: true, release: true); + } + + /// exportedTypeWithIdentifier:conformingToType: + static UTType exportedTypeWithIdentifier$1( + objc.NSString identifier, { + required UTType conformingToType, + }) { + objc.checkOsVersionInternal( + 'UTType.exportedTypeWithIdentifier:conformingToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _class_UTType, + _sel_exportedTypeWithIdentifier_conformingToType_, + identifier.ref.pointer, + conformingToType.ref.pointer, + ); + return UTType.fromPointer($ret, retain: true, release: true); + } + + /// importedTypeWithIdentifier: + static UTType importedTypeWithIdentifier(objc.NSString identifier) { + objc.checkOsVersionInternal( + 'UTType.importedTypeWithIdentifier:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _class_UTType, + _sel_importedTypeWithIdentifier_, + identifier.ref.pointer, + ); + return UTType.fromPointer($ret, retain: true, release: true); + } + + /// importedTypeWithIdentifier:conformingToType: + static UTType importedTypeWithIdentifier$1( + objc.NSString identifier, { + required UTType conformingToType, + }) { + objc.checkOsVersionInternal( + 'UTType.importedTypeWithIdentifier:conformingToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _class_UTType, + _sel_importedTypeWithIdentifier_conformingToType_, + identifier.ref.pointer, + conformingToType.ref.pointer, + ); + return UTType.fromPointer($ret, retain: true, release: true); + } +} + +/// UTType +extension type UTType._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying, objc.NSSecureCoding { + /// Constructs a [UTType] that points to the same underlying object as [other]. + UTType.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal('UTType', iOS: (false, (14, 0, 0)), macOS: (false, (11, 0, 0))); + assert(isA(object$)); + } + + /// Constructs a [UTType] that wraps the given raw object pointer. + UTType.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal('UTType', iOS: (false, (14, 0, 0)), macOS: (false, (11, 0, 0))); + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [UTType]. + static bool isA(objc.ObjCObject obj) => + _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_UTType); +} + +extension UTType$Methods on UTType { + /// preferredMIMEType + objc.NSString? get preferredMIMEType { + objc.checkOsVersionInternal( + 'UTType.preferredMIMEType', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_preferredMIMEType); + return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); + } +} + late final _sel_provideImageData_bytesPerRow_origin__size__userInfo_ = objc.registerName( "provideImageData:bytesPerRow:origin::size::userInfo:", ); @@ -4357,6 +4565,7 @@ final _objc_msgSend_1or4ucj = objc.msgSendPointer >() .asFunction, ffi.Pointer)>(); late final _sel_originalFilename = objc.registerName("originalFilename"); +late final _sel_contentType = objc.registerName("contentType"); late final _sel_assetResourcesForAsset_ = objc.registerName("assetResourcesForAsset:"); /// PHAssetResource @@ -4407,6 +4616,17 @@ extension type PHAssetResource._(objc.ObjCObject object$) } extension PHAssetResource$Methods on PHAssetResource { + /// contentType + UTType get contentType { + objc.checkOsVersionInternal( + 'PHAssetResource.contentType', + iOS: (false, (26, 0, 0)), + macOS: (false, (26, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_contentType); + return UTType.fromPointer($ret, retain: true, release: true); + } + /// originalFilename objc.NSString get originalFilename { objc.checkOsVersionInternal( diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 6fcd1b9250ba..0b4bb052616b 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -17,9 +17,7 @@ void main() { ), headers: Headers( entryPoints: [ - Uri.file( - '$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/Photos.h', - ), + Uri.file('$macSdkPath/System/Library/Frameworks/Photos.framework/Headers/Photos.h'), ], compilerOptions: ['-include stdint.h'], ), @@ -36,6 +34,7 @@ void main() { 'PHFetchResult', 'PHImageManager', 'PHImageRequestOptions', + 'UTType', }.contains(declaration.originalName); }, includeMember: (Declaration declaration, String member) { @@ -53,6 +52,7 @@ void main() { }.contains(signature), 'PHAssetResource' => { 'assetResourcesForAsset:', + 'contentType', 'originalFilename', 'type', }.contains(signature), @@ -69,11 +69,11 @@ void main() { 'new', 'setNetworkAccessAllowed:', }.contains(signature), + 'UTType' => {'preferredMIMEType'}.contains(signature), _ => false, }; }, ), - ), ).generate(); } From eaede7b16f51951d853951042b6c55db44b9084d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 18:42:46 -0400 Subject: [PATCH 287/398] print extractor --- .../lib/src/darwin_scoped_storage_cross_file.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index cd7ffb3d251a..9b57eea78d6f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -364,7 +364,9 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final Pointer uint8Pointer = data.bytes.cast(); final Uint8List byteView = uint8Pointer.asTypedList(data.length); - return Uint8List.fromList(byteView); + final a = Uint8List.fromList(byteView); + print('extract: ${a[0]} ${a[1]}'); + return a; } } From 2ebe107867116f3d14eecafd310131ad4a5caea5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 19:01:40 -0400 Subject: [PATCH 288/398] print length --- .../lib/src/darwin_scoped_storage_cross_file.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 9b57eea78d6f..dfe5ec8665f7 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -358,6 +358,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } Uint8List _extractBytesToUint8List(NSData data) { + print('hoho: ${data.length}'); if (data.length == 0) { return Uint8List(0); } From c22d4bc9654cd915aa1c641d69c0265c44b77b84 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 19:07:41 -0400 Subject: [PATCH 289/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index dfe5ec8665f7..95cb79481b8b 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -358,7 +358,6 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } Uint8List _extractBytesToUint8List(NSData data) { - print('hoho: ${data.length}'); if (data.length == 0) { return Uint8List(0); } @@ -367,6 +366,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final Uint8List byteView = uint8Pointer.asTypedList(data.length); final a = Uint8List.fromList(byteView); print('extract: ${a[0]} ${a[1]}'); + print('extract: ${a[a.length - 1]}'); + print('extract: ${a[a.length - 2]}'); return a; } } From 4492f9cbb0439d6b93c5b65f84398e768b4a5f52 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 19:19:51 -0400 Subject: [PATCH 290/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 95cb79481b8b..d624dc9cceac 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -365,7 +365,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final Pointer uint8Pointer = data.bytes.cast(); final Uint8List byteView = uint8Pointer.asTypedList(data.length); final a = Uint8List.fromList(byteView); - print('extract: ${a[0]} ${a[1]}'); + print('extract: ${a[0]} ${a[1]} ${a[2]} ${a[3]} ${a[4]}'); print('extract: ${a[a.length - 1]}'); print('extract: ${a[a.length - 2]}'); return a; From c1fddbb782a256d08e87781f7255fbf488037d3e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 19:30:59 -0400 Subject: [PATCH 291/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index d624dc9cceac..d9a7d1597d3e 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -358,6 +358,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } Uint8List _extractBytesToUint8List(NSData data) { + print('start extract'); + print(data.hashCode); if (data.length == 0) { return Uint8List(0); } From dc66e880e585b2f459a3ac82c9744cfa1ec7d31c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 8 Jun 2026 20:01:59 -0400 Subject: [PATCH 292/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index d9a7d1597d3e..7749bec2f87d 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -261,7 +261,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile resourceManager.requestDataForAssetResource( resource, - dataReceivedHandler: ObjCBlock_ffiVoid_NSData.listener(dataReceivedHandler), + dataReceivedHandler: ObjCBlock_ffiVoid_NSData.fromFunction(dataReceivedHandler), completionHandler: ObjCBlock_ffiVoid_NSError.listener(completionHandler), ); From 10cdaa63f48ce5bd34790177fd2f244f6ca61dd6 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:44:25 -0400 Subject: [PATCH 293/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 7749bec2f87d..ecd33dc56cf7 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -262,7 +262,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile resourceManager.requestDataForAssetResource( resource, dataReceivedHandler: ObjCBlock_ffiVoid_NSData.fromFunction(dataReceivedHandler), - completionHandler: ObjCBlock_ffiVoid_NSError.listener(completionHandler), + completionHandler: ObjCBlock_ffiVoid_NSError.blocking(completionHandler), ); return streamController.stream; From 75446713ede7e4143279505e3b0920d8fc4856dd Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 9 Jun 2026 14:14:28 -0400 Subject: [PATCH 294/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index ecd33dc56cf7..a500272f5e0d 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -262,7 +262,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile resourceManager.requestDataForAssetResource( resource, dataReceivedHandler: ObjCBlock_ffiVoid_NSData.fromFunction(dataReceivedHandler), - completionHandler: ObjCBlock_ffiVoid_NSError.blocking(completionHandler), + completionHandler: ObjCBlock_ffiVoid_NSError.listener(completionHandler), ); return streamController.stream; @@ -358,8 +358,6 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } Uint8List _extractBytesToUint8List(NSData data) { - print('start extract'); - print(data.hashCode); if (data.length == 0) { return Uint8List(0); } From b38c571cfb15e72b202a80ca80e616fb7140ad6d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 9 Jun 2026 16:26:37 -0400 Subject: [PATCH 295/398] something something --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index a500272f5e0d..d624dc9cceac 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -261,7 +261,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile resourceManager.requestDataForAssetResource( resource, - dataReceivedHandler: ObjCBlock_ffiVoid_NSData.fromFunction(dataReceivedHandler), + dataReceivedHandler: ObjCBlock_ffiVoid_NSData.listener(dataReceivedHandler), completionHandler: ObjCBlock_ffiVoid_NSError.listener(completionHandler), ); From 431cf874c1e63f139c100905d43864ce5a1092de Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 12 Jun 2026 16:32:14 -0400 Subject: [PATCH 296/398] start of chaning open read to proxyapi --- .../CrossFileDarwinApis.g.swift | 602 +++++++++++-- .../lib/src/cross_file_darwin_apis.g.dart | 789 +++++++++++++++--- .../src/darwin_scoped_storage_cross_file.dart | 42 +- .../pigeons/cross_file_darwin_apis.dart | 47 +- 4 files changed, 1230 insertions(+), 250 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index dab17ef13048..6dade73fe2db 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -58,6 +58,10 @@ private func wrapError(_ error: Any) -> [Any?] { ] } +private func createConnectionError(withChannelName channelName: String) -> PigeonError { + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") +} + private func isNullish(_ value: Any?) -> Bool { return value is NSNull || value == nil } @@ -67,6 +71,427 @@ private func nilOrValue(_ value: Any?) -> T? { return value as! T? } +/// Handles the callback when an object is deallocated. +protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { + /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. + func onDeinit(identifier: Int64) +} + + +// Attaches to an object to receive a callback when the object is deallocated. +internal final class CrossFileDarwinApisPigeonInternalFinalizer { + internal static let associatedObjectKey = malloc(1)! + + private let identifier: Int64 + // Reference to the delegate is weak because the callback should be ignored if the + // `InstanceManager` is deallocated. + internal weak var delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate? + + private init(identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { + self.identifier = identifier + self.delegate = delegate + } + + internal static func attach( + to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + ) { + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) + } + + static func detach(from instance: AnyObject) { + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + if let finalizer = finalizer { + finalizer.delegate = nil + objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) + } + } + + deinit { + delegate?.onDeinit(identifier: identifier) + } +} + + +/// Maintains instances used to communicate with the corresponding objects in Dart. +/// +/// Objects stored in this container are represented by an object in Dart that is also stored in +/// an InstanceManager with the same identifier. +/// +/// When an instance is added with an identifier, either can be used to retrieve the other. +/// +/// Added instances are added as a weak reference and a strong reference. When the strong +/// reference is removed and the weak reference is deallocated,`CrossFileDarwinApisPigeonInternalFinalizerDelegate.onDeinit` +/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is +/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), +/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually +/// again. +/// +/// Accessing and inserting to an InstanceManager is thread safe. +final class CrossFileDarwinApisPigeonInstanceManager { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private static let minHostCreatedIdentifier: Int64 = 65536 + + private let lockQueue = DispatchQueue(label: "CrossFileDarwinApisPigeonInstanceManager") + private let identifiers: NSMapTable = NSMapTable( + keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) + private let weakInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) + private let strongInstances: NSMapTable = NSMapTable( + keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) + private let finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + private var nextIdentifier: Int64 = minHostCreatedIdentifier + + public init(finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { + self.finalizerDelegate = finalizerDelegate + } + + /// Adds a new instance that was instantiated from Dart. + /// + /// The same instance can be added multiple times, but each identifier must be unique. This allows + /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. + /// + /// - Parameters: + /// - instance: the instance to be stored + /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique + func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + lockQueue.async { + self.addInstance(instance, withIdentifier: identifier) + } + } + + /// Adds a new instance that was instantiated from the host platform. + /// + /// - Parameters: + /// - instance: the instance to be stored. This must be unique to all other added instances. + /// - Returns: the unique identifier (>= 0) stored with instance + func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { + assert(!containsInstance(instance), "Instance of \(instance) has already been added.") + var identifier: Int64 = -1 + lockQueue.sync { + identifier = nextIdentifier + nextIdentifier += 1 + self.addInstance(instance, withIdentifier: identifier) + } + return identifier + } + + /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier paired to an instance. + /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if + /// the manager doesn't contain the value + func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) + strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + /// Retrieves the instance associated with identifier. + /// + /// - Parameters: + /// - instanceIdentifier: the identifier associated with an instance + /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func instance(forIdentifier instanceIdentifier: Int64) -> T? { + var instance: AnyObject? = nil + lockQueue.sync { + instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) + } + return instance as? T + } + + private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { + assert(identifier >= 0) + assert( + weakInstances.object(forKey: identifier as NSNumber) == nil, + "Identifier has already been added: \(identifier)") + identifiers.setObject(NSNumber(value: identifier), forKey: instance) + weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) + strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) + CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + } + + /// Retrieves the identifier paired with an instance. + /// + /// If the manager contains a strong reference to `instance`, it will return the identifier + /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new + /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. + /// + /// If this method returns a nonnull identifier, this method also expects the Dart + /// `CrossFileDarwinApisPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + /// identifier is associated with. + /// + /// - Parameters: + /// - instance: an instance that may be stored in the manager + /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise + /// `nil` if the manager doesn't contain the value + func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { + var identifier: Int64? = nil + lockQueue.sync { + if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { + strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) + identifier = existingIdentifier + } + } + return identifier + } + + /// Whether this manager contains the given `instance`. + /// + /// - Parameters: + /// - instance: the instance whose presence in this manager is to be tested + /// - Returns: whether this manager contains the given `instance` + func containsInstance(_ instance: AnyObject) -> Bool { + var containsInstance = false + lockQueue.sync { + containsInstance = identifiers.object(forKey: instance) != nil + } + return containsInstance + } + + /// Removes all of the instances from this manager. + /// + /// The manager will be empty after this call returns. + func removeAllObjects() throws { + lockQueue.sync { + let weakInstancesEnumerator = weakInstances.objectEnumerator()! + while let instance = weakInstancesEnumerator.nextObject() { + CrossFileDarwinApisPigeonInternalFinalizer.detach(from: instance as AnyObject) + } + identifiers.removeAllObjects() + weakInstances.removeAllObjects() + strongInstances.removeAllObjects() + nextIdentifier = CrossFileDarwinApisPigeonInstanceManager.minHostCreatedIdentifier + } + } + + /// The number of instances stored as a strong reference. + /// + /// For debugging and testing purposes. + internal var strongInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = strongInstances.count + } + return count + } + + /// The number of instances stored as a weak reference. + /// + /// For debugging and testing purposes. NSMapTables that store keys or objects as weak + /// reference will be reclaimed non-deterministically. + internal var weakInstanceCount: Int { + var count: Int = 0 + lockQueue.sync { + count = weakInstances.count + } + return count + } +} + + +private class CrossFileDarwinApisPigeonInstanceManagerApi { + /// The codec used for serializing messages. + var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } + + /// Handles sending and receiving messages with Dart. + unowned let binaryMessenger: FlutterBinaryMessenger + + init(binaryMessenger: FlutterBinaryMessenger) { + self.binaryMessenger = binaryMessenger + } + + /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + let codec = CrossFileDarwinApisPigeonCodec.shared + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + removeStrongReferenceChannel.setMessageHandler { message, reply in + let args = message as! [Any?] + let identifierArg = args[0] as! Int64 + do { + let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + removeStrongReferenceChannel.setMessageHandler(nil) + } + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + if let instanceManager = instanceManager { + clearChannel.setMessageHandler { _, reply in + do { + try instanceManager.removeAllObjects() + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + clearChannel.setMessageHandler(nil) + } + } + + /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([identifierArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } +} +protocol CrossFileDarwinApisPigeonProxyApiDelegate { + /// An implementation of [PigeonApiAssetResourceManagerBytesListener] used to add a new Dart instance of + /// `AssetResourceManagerBytesListener` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiAssetResourceManagerBytesListener(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceManagerBytesListener +} + +open class CrossFileDarwinApisPigeonProxyApiRegistrar { + let binaryMessenger: FlutterBinaryMessenger + let apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + let instanceManager: CrossFileDarwinApisPigeonInstanceManager + /// Whether APIs should ignore calling to Dart. + public var ignoreCallsToDart = false + private var _codec: FlutterStandardMessageCodec? + var codec: FlutterStandardMessageCodec { + if _codec == nil { + _codec = FlutterStandardMessageCodec( + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + } + return _codec! + } + + private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + let api: CrossFileDarwinApisPigeonInstanceManagerApi + + init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { + self.api = api + } + + public func onDeinit(identifier: Int64) { + api.removeStrongReference(identifier: identifier) { + _ in + } + } + } + + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + self.binaryMessenger = binaryMessenger + self.apiDelegate = apiDelegate + self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( + finalizerDelegate: InstanceManagerApiFinalizerDelegate( + CrossFileDarwinApisPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) + } + + func setUp() { + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiAssetResourceManagerBytesListener.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceManagerBytesListener(self)) + } + func tearDown() { + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + PigeonApiAssetResourceManagerBytesListener.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + } +} +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func readValue(ofType type: UInt8) -> Any? { + switch type { + case 128: + let identifier = self.readValue() + let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( + forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) + if instance == nil { + print("Failed to find instance with identifier: \(identifier!)") + } + return instance + default: + return super.readValue(ofType: type) + } + } + } + + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + + init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + super.init(data: data) + } + + override func writeValue(_ value: Any) { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + super.writeValue(value) + return + } + + + if let instance = value as? AssetResourceManagerBytesListener { + pigeonRegistrar.apiDelegate.pigeonApiAssetResourceManagerBytesListener(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + return + } + + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + { + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) + } else { + print("Unsupported value: \(value) of \(type(of: value))") + assert(false, "Unsupported value for CrossFileDarwinApisPigeonInternalProxyApiCodecWriter") + } + + } + } + + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { + self.pigeonRegistrar = pigeonRegistrar + } + + override func reader(with data: Data) -> FlutterStandardReader { + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + } + + override func writer(with data: NSMutableData) -> FlutterStandardWriter { + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + } +} private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { } @@ -88,75 +513,152 @@ class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Se static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } -/// Api for getting access to file information. -/// -/// Generated protocol from Pigeon that represents a handler of messages from Flutter. -protocol CrossFileDarwinApi { - /// In an app that has adopted App Sandbox, makes the resource pointed to by a - /// security-scoped URL available to the app. - func startAccessingSecurityScopedResource(url: String) throws -> Bool - /// In an app that adopts App Sandbox, revokes access to the resource pointed - /// to by a security-scoped URL. - func stopAccessingSecurityScopedResource(url: String) throws - /// Whether the native FileManager is able to read a specified file. - func isReadableFile(url: String) throws -> Bool -} - -/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`. -class CrossFileDarwinApiSetup { - static var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } - /// Sets up an instance of `CrossFileDarwinApi` to handle messages through the `binaryMessenger`. - static func setUp(binaryMessenger: FlutterBinaryMessenger, api: CrossFileDarwinApi?, messageChannelSuffix: String = "") { - let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : "" - /// In an app that has adopted App Sandbox, makes the resource pointed to by a - /// security-scoped URL available to the app. - let startAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - startAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let urlArg = args[0] as! String - do { - let result = try api.startAccessingSecurityScopedResource(url: urlArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - startAccessingSecurityScopedResourceChannel.setMessageHandler(nil) - } - /// In an app that adopts App Sandbox, revokes access to the resource pointed - /// to by a security-scoped URL. - let stopAccessingSecurityScopedResourceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) +protocol PigeonApiDelegateAssetResourceManagerBytesListener { + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceManagerBytesListener) throws -> AssetResourceManagerBytesListener + func openRead(pigeonApi: PigeonApiAssetResourceManagerBytesListener, pigeonInstance: AssetResourceManagerBytesListener, localIdentifier: String) throws -> Bool +} + +protocol PigeonApiProtocolAssetResourceManagerBytesListener { + func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) + func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, error errorArg: String?, completion: @escaping (Result) -> Void) +} + +final class PigeonApiAssetResourceManagerBytesListener: PigeonApiProtocolAssetResourceManagerBytesListener { + unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateAssetResourceManagerBytesListener + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateAssetResourceManagerBytesListener) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceManagerBytesListener?) { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.pigeon_defaultConstructor", binaryMessenger: binaryMessenger, codec: codec) if let api = api { - stopAccessingSecurityScopedResourceChannel.setMessageHandler { message, reply in + pigeonDefaultConstructorChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let urlArg = args[0] as! String + let pigeonIdentifierArg = args[0] as! Int64 do { - try api.stopAccessingSecurityScopedResource(url: urlArg) + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( +try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), +withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) } } } else { - stopAccessingSecurityScopedResourceChannel.setMessageHandler(nil) + pigeonDefaultConstructorChannel.setMessageHandler(nil) } - /// Whether the native FileManager is able to read a specified file. - let isReadableFileChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec) + let openReadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.openRead", binaryMessenger: binaryMessenger, codec: codec) if let api = api { - isReadableFileChannel.setMessageHandler { message, reply in + openReadChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let urlArg = args[0] as! String + let pigeonInstanceArg = args[0] as! AssetResourceManagerBytesListener + let localIdentifierArg = args[1] as! String do { - let result = try api.isReadableFile(url: urlArg) + let result = try api.pigeonDelegate.openRead(pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) } } } else { - isReadableFileChannel.setMessageHandler(nil) + openReadChannel.setMessageHandler(nil) + } + } + + ///Creates a Dart instance of AssetResourceManagerBytesListener and attaches it to [pigeonInstance]. + func pigeonNewInstance(pigeonInstance: AssetResourceManagerBytesListener, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + completion(.success(())) + } else { + completion( + .failure( + PigeonError( + code: "new-instance-error", + message: "Error: Attempting to create a new Dart instance of AssetResourceManagerBytesListener, but the class has a nonnull callback method.", details: ""))) + } + } + func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + completion( + .failure( + PigeonError( + code: "missing-instance-error", + message: "Callback to `AssetResourceManagerBytesListener.onDataReceived` failed because native instance was not in the instance manager.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onDataReceived" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, bytesArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } + } + } + + func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, error errorArg: String?, completion: @escaping (Result) -> Void) { + if pigeonRegistrar.ignoreCallsToDart { + completion( + .failure( + PigeonError( + code: "ignore-calls-error", + message: "Calls to Dart are being ignored.", details: ""))) + return + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + completion( + .failure( + PigeonError( + code: "missing-instance-error", + message: "Callback to `AssetResourceManagerBytesListener.onCompletion` failed because native instance was not in the instance manager.", details: ""))) + return + } + let binaryMessenger = pigeonRegistrar.binaryMessenger + let codec = pigeonRegistrar.codec + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onCompletion" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + channel.sendMessage([pigeonInstanceArg, errorArg] as [Any?]) { response in + guard let listResponse = response as? [Any?] else { + completion(.failure(createConnectionError(withChannelName: channelName))) + return + } + if listResponse.count > 1 { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(PigeonError(code: code, message: message, details: details))) + } else { + completion(.success(())) + } } } + } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 8b80166fe413..6d6c486e732d 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -1,137 +1,652 @@ -// // Copyright 2013 The Flutter Authors -// // Use of this source code is governed by a BSD-style license that can be -// // found in the LICENSE file. -// // Autogenerated from Pigeon (v26.3.4), do not edit directly. -// // See also: https://pub.dev/packages/pigeon -// // ignore_for_file: unused_import, unused_shown_name -// // ignore_for_file: type=lint -// -// import 'dart:async'; -// import 'dart:typed_data' show Float64List, Int32List, Int64List; -// -// import 'package:flutter/services.dart'; -// import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; -// -// Object? _extractReplyValueOrThrow( -// List? replyList, -// String channelName, { -// required bool isNullValid, -// }) { -// if (replyList == null) { -// throw PlatformException( -// code: 'channel-error', -// message: 'Unable to establish connection on channel: "$channelName".', -// ); -// } else if (replyList.length > 1) { -// throw PlatformException( -// code: replyList[0]! as String, -// message: replyList[1] as String?, -// details: replyList[2], -// ); -// } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { -// throw PlatformException( -// code: 'null-error', -// message: 'Host platform returned null value for non-null return value.', -// ); -// } -// return replyList.firstOrNull; -// } -// -// -// -// class _PigeonCodec extends StandardMessageCodec { -// const _PigeonCodec(); -// @override -// void writeValue(WriteBuffer buffer, Object? value) { -// if (value is int) { -// buffer.putUint8(4); -// buffer.putInt64(value); -// } else { -// super.writeValue(buffer, value); -// } -// } -// -// @override -// Object? readValueOfType(int type, ReadBuffer buffer) { -// switch (type) { -// default: -// return super.readValueOfType(type, buffer); -// } -// } -// } -// -// /// Api for getting access to file information. -// class CrossFileDarwinApi { -// /// Constructor for [CrossFileDarwinApi]. The [binaryMessenger] named argument is -// /// available for dependency injection. If it is left null, the default -// /// BinaryMessenger will be used which routes to the host platform. -// CrossFileDarwinApi({BinaryMessenger? binaryMessenger, String messageChannelSuffix = ''}) -// : pigeonVar_binaryMessenger = binaryMessenger, -// pigeonVar_messageChannelSuffix = messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : ''; -// final BinaryMessenger? pigeonVar_binaryMessenger; -// -// static const MessageCodec pigeonChannelCodec = _PigeonCodec(); -// -// final String pigeonVar_messageChannelSuffix; -// -// /// In an app that has adopted App Sandbox, makes the resource pointed to by a -// /// security-scoped URL available to the app. -// Future startAccessingSecurityScopedResource(String url) async { -// final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.startAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; -// final pigeonVar_channel = BasicMessageChannel( -// pigeonVar_channelName, -// pigeonChannelCodec, -// binaryMessenger: pigeonVar_binaryMessenger, -// ); -// final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); -// final pigeonVar_replyList = await pigeonVar_sendFuture as List?; -// -// final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( -// pigeonVar_replyList, -// pigeonVar_channelName, -// isNullValid: false, -// ) -// ; -// return pigeonVar_replyValue! as bool; -// } -// -// /// In an app that adopts App Sandbox, revokes access to the resource pointed -// /// to by a security-scoped URL. -// Future stopAccessingSecurityScopedResource(String url) async { -// final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.stopAccessingSecurityScopedResource$pigeonVar_messageChannelSuffix'; -// final pigeonVar_channel = BasicMessageChannel( -// pigeonVar_channelName, -// pigeonChannelCodec, -// binaryMessenger: pigeonVar_binaryMessenger, -// ); -// final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); -// final pigeonVar_replyList = await pigeonVar_sendFuture as List?; -// -// _extractReplyValueOrThrow( -// pigeonVar_replyList, -// pigeonVar_channelName, -// isNullValid: true, -// ) -// ; -// } -// -// /// Whether the native FileManager is able to read a specified file. -// Future isReadableFile(String url) async { -// final pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.CrossFileDarwinApi.isReadableFile$pigeonVar_messageChannelSuffix'; -// final pigeonVar_channel = BasicMessageChannel( -// pigeonVar_channelName, -// pigeonChannelCodec, -// binaryMessenger: pigeonVar_binaryMessenger, -// ); -// final Future pigeonVar_sendFuture = pigeonVar_channel.send([url]); -// final pigeonVar_replyList = await pigeonVar_sendFuture as List?; -// -// final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( -// pigeonVar_replyList, -// pigeonVar_channelName, -// isNullValid: false, -// ) -// ; -// return pigeonVar_replyValue! as bool; -// } -// } +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// Autogenerated from Pigeon (v26.3.4), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: unused_import, unused_shown_name +// ignore_for_file: type=lint + +import 'dart:async'; +import 'dart:io' show Platform; +import 'dart:typed_data' show Float64List, Int32List, Int64List; + +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; +import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; + +Object? _extractReplyValueOrThrow( + List? replyList, + String channelName, { + required bool isNullValid, +}) { + if (replyList == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel: "$channelName".', + ); + } else if (replyList.length > 1) { + throw PlatformException( + code: replyList[0]! as String, + message: replyList[1] as String?, + details: replyList[2], + ); + } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } + return replyList.firstOrNull; +} + +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + +/// Provides overrides for the constructors and static members of each +/// Dart proxy class. +/// +/// This is only intended to be used with unit tests to prevent errors from +/// making message calls in a unit test. +/// +/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. +@visibleForTesting +class PigeonOverrides { + /// Overrides [AssetResourceManagerBytesListener.new]. + static AssetResourceManagerBytesListener Function({ + required void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes) + onDataReceived, + required void Function(AssetResourceManagerBytesListener pigeon_instance, String? error) + onCompletion, + })? + assetResourceManagerBytesListener_new; + + /// Sets all overridden ProxyApi class members to null. + static void pigeon_reset() { + assetResourceManagerBytesListener_new = null; + } +} + +/// An immutable object that serves as the base class for all Dart proxy classes +/// and can provide functional copies of itself. +/// +/// All implementers are expected to be [immutable] as defined by the annotation +/// and override [pigeon_copy] returning an instance of itself. +@immutable +abstract class PigeonInternalProxyApiBaseClass { + /// Construct a [PigeonInternalProxyApiBaseClass]. + PigeonInternalProxyApiBaseClass({ + this.pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + }) : pigeon_instanceManager = pigeon_instanceManager ?? PigeonInstanceManager.instance; + + /// Sends and receives binary data across the Flutter platform barrier. + /// + /// If it is null, the default BinaryMessenger will be used, which routes to + /// the host platform. + @protected + final BinaryMessenger? pigeon_binaryMessenger; + + /// Maintains instances stored to communicate with native language objects. + final PigeonInstanceManager pigeon_instanceManager; + + /// Instantiates and returns a functionally identical object to oneself. + /// + /// Outside of tests, this method should only ever be called by + /// [PigeonInstanceManager]. + /// + /// Subclasses should always override their parent's implementation of this + /// method. + @protected + PigeonInternalProxyApiBaseClass pigeon_copy(); +} + +/// Maintains instances used to communicate with the native objects they +/// represent. +/// +/// Added instances are stored as weak references and their copies are stored +/// as strong references to maintain access to their variables and callback +/// methods. Both are stored with the same identifier. +/// +/// When a weak referenced instance becomes inaccessible, +/// [onWeakReferenceRemoved] is called with its associated identifier. +/// +/// If an instance is retrieved and has the possibility to be used, +/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference +/// is added as a weak reference with the same identifier. This prevents a +/// scenario where the weak referenced instance was released and then later +/// returned by the host platform. +class PigeonInstanceManager { + /// Constructs a [PigeonInstanceManager]. + PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { + this.onWeakReferenceRemoved = (int identifier) { + _weakInstances.remove(identifier); + onWeakReferenceRemoved(identifier); + }; + _finalizer = Finalizer(this.onWeakReferenceRemoved); + } + + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously by the host platform. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + static const int _maxDartCreatedIdentifier = 65536; + + /// The default [PigeonInstanceManager] used by Dart proxy classes. + /// + /// On creation, this manager makes a call to clear the native + /// InstanceManager. This is to prevent identifier conflicts after a host + /// restart. + static final PigeonInstanceManager instance = _initInstance(); + + // Expando is used because it doesn't prevent its keys from becoming + // inaccessible. This allows the manager to efficiently retrieve an identifier + // of an instance without holding a strong reference to that instance. + // + // It also doesn't use `==` to search for identifiers, which would lead to an + // infinite loop when comparing an object to its copy. (i.e. which was caused + // by calling instanceManager.getIdentifier() inside of `==` while this was a + // HashMap). + final Expando _identifiers = Expando(); + final Map> _weakInstances = + >{}; + final Map _strongInstances = + {}; + late final Finalizer _finalizer; + int _nextIdentifier = 0; + + /// Called when a weak referenced instance is removed by [removeWeakReference] + /// or becomes inaccessible. + late final void Function(int) onWeakReferenceRemoved; + + static PigeonInstanceManager _initInstance() { + if (Platform.environment['FLUTTER_TEST'] == 'true') { + return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); + } + WidgetsFlutterBinding.ensureInitialized(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); + // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. + api.clear(); + final PigeonInstanceManager instanceManager = PigeonInstanceManager( + onWeakReferenceRemoved: (int identifier) { + api.removeStrongReference(identifier); + }, + ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + AssetResourceManagerBytesListener.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); + return instanceManager; + } + + /// Adds a new instance that was instantiated by Dart. + /// + /// In other words, Dart wants to add a new instance that will represent + /// an object that will be instantiated on the host platform. + /// + /// Throws assertion error if the instance has already been added. + /// + /// Returns the randomly generated id of the [instance] added. + int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { + assert(getIdentifier(instance) == null); + + final int identifier = _nextUniqueIdentifier(); + _identifiers[instance] = identifier; + _weakInstances[identifier] = WeakReference(instance); + _finalizer.attach(instance, identifier, detach: instance); + + final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); + _identifiers[copy] = identifier; + _strongInstances[identifier] = copy; + return identifier; + } + + /// Removes the instance, if present, and call [onWeakReferenceRemoved] with + /// its identifier. + /// + /// Returns the identifier associated with the removed instance. Otherwise, + /// `null` if the instance was not found in this manager. + /// + /// This does not remove the strong referenced instance associated with + /// [instance]. This can be done with [remove]. + int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { + final int? identifier = getIdentifier(instance); + if (identifier == null) { + return null; + } + + _identifiers[instance] = null; + _finalizer.detach(instance); + onWeakReferenceRemoved(identifier); + + return identifier; + } + + /// Removes [identifier] and its associated strongly referenced instance, if + /// present, from the manager. + /// + /// Returns the strong referenced instance associated with [identifier] before + /// it was removed. Returns `null` if [identifier] was not associated with + /// any strong reference. + /// + /// Throws an `AssertionError` if the weak referenced instance associated with + /// [identifier] is not removed first. This can be done with + /// [removeWeakReference]. + T? remove(int identifier) { + final T? instance = _weakInstances[identifier]?.target as T?; + assert( + instance == null, + 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', + ); + return _strongInstances.remove(identifier) as T?; + } + + /// Retrieves the instance associated with identifier. + /// + /// The value returned is chosen from the following order: + /// + /// 1. A weakly referenced instance associated with identifier. + /// 2. If the only instance associated with identifier is a strongly + /// referenced instance, a copy of the instance is added as a weak reference + /// with the same identifier. Returning the newly created copy. + /// 3. If no instance is associated with identifier, returns null. + /// + /// This method also expects the host `InstanceManager` to have a strong + /// reference to the instance the identifier is associated with. + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; + + if (weakInstance == null) { + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; + if (strongInstance != null) { + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); + _identifiers[copy] = identifier; + _weakInstances[identifier] = WeakReference(copy); + _finalizer.attach(copy, identifier, detach: copy); + return copy as T; + } + return strongInstance as T?; + } + + return weakInstance as T; + } + + /// Retrieves the identifier associated with instance. + int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { + return _identifiers[instance]; + } + + /// Adds a new instance that was instantiated by the host platform. + /// + /// In other words, the host platform wants to add a new instance that + /// represents an object on the host platform. Stored with [identifier]. + /// + /// Throws assertion error if the instance or its identifier has already been + /// added. + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { + assert(!containsIdentifier(identifier)); + assert(getIdentifier(instance) == null); + assert(identifier >= 0); + + _identifiers[instance] = identifier; + _strongInstances[identifier] = instance; + } + + /// Whether this manager contains the given [identifier]. + bool containsIdentifier(int identifier) { + return _weakInstances.containsKey(identifier) || _strongInstances.containsKey(identifier); + } + + int _nextUniqueIdentifier() { + late int identifier; + do { + identifier = _nextIdentifier; + _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; + } while (containsIdentifier(identifier)); + return identifier; + } +} + +/// Generated API for managing the Dart and native `PigeonInstanceManager`s. +class _PigeonInternalInstanceManagerApi { + /// Constructor for [_PigeonInternalInstanceManagerApi]. + _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) + : pigeonVar_binaryMessenger = binaryMessenger; + + final BinaryMessenger? pigeonVar_binaryMessenger; + + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); + + static void setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? binaryMessenger, + PigeonInstanceManager? instanceManager, + }) { + { + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + final List args = message! as List; + final int arg_identifier = args[0]! as int; + try { + (instanceManager ?? PigeonInstanceManager.instance).remove(arg_identifier); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } + }); + } + } + } + + Future removeStrongReference(int identifier) async { + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([identifier]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); + } + + /// Clear the native `PigeonInstanceManager`. + /// + /// This is typically called after a hot restart. + Future clear() async { + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); + } +} + +class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} + +class _PigeonCodec extends StandardMessageCodec { + const _PigeonCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is int) { + buffer.putUint8(4); + buffer.putInt64(value); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + default: + return super.readValueOfType(type, buffer); + } + } +} + +/// Api for getting access to file information. +class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass { + factory AssetResourceManagerBytesListener({ + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + required void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes) + onDataReceived, + required void Function(AssetResourceManagerBytesListener pigeon_instance, String? error) + onCompletion, + }) { + if (PigeonOverrides.assetResourceManagerBytesListener_new != null) { + return PigeonOverrides.assetResourceManagerBytesListener_new!( + onDataReceived: onDataReceived, + onCompletion: onCompletion, + ); + } + return AssetResourceManagerBytesListener.pigeon_new( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + onDataReceived: onDataReceived, + onCompletion: onCompletion, + ); + } + + @protected + AssetResourceManagerBytesListener.pigeon_new({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.onDataReceived, + required this.onCompletion, + }) { + final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecAssetResourceManagerBytesListener; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.pigeon_defaultConstructor'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + ]); + () async { + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); + }(); + } + + /// Constructs [AssetResourceManagerBytesListener] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + AssetResourceManagerBytesListener.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + required this.onDataReceived, + required this.onCompletion, + }); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceManagerBytesListener = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + /// Callback method. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final AssetResourceManagerBytesListener instance = AssetResourceManagerBytesListener( + /// onDataReceived: (AssetResourceManagerBytesListener pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes) + onDataReceived; + + /// Callback method. + /// + /// For the associated Native object to be automatically garbage collected, + /// it is required that the implementation of this `Function` doesn't have a + /// strong reference to the encapsulating class instance. When this `Function` + /// references a non-local variable, it is strongly recommended to access it + /// with a `WeakReference`: + /// + /// ```dart + /// final WeakReference weakMyVariable = WeakReference(myVariable); + /// final AssetResourceManagerBytesListener instance = AssetResourceManagerBytesListener( + /// onCompletion: (AssetResourceManagerBytesListener pigeon_instance, ...) { + /// print(weakMyVariable?.target); + /// }, + /// ); + /// ``` + /// + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to + /// release the associated Native object manually. + final void Function(AssetResourceManagerBytesListener pigeon_instance, String? error) + onCompletion; + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes)? + onDataReceived, + void Function(AssetResourceManagerBytesListener pigeon_instance, String? error)? onCompletion, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onDataReceived', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + final List args = message! as List; + final AssetResourceManagerBytesListener arg_pigeon_instance = + args[0]! as AssetResourceManagerBytesListener; + final Uint8List arg_bytes = args[1]! as Uint8List; + try { + (onDataReceived ?? arg_pigeon_instance.onDataReceived).call( + arg_pigeon_instance, + arg_bytes, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } + }); + } + } + + { + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onCompletion', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + final List args = message! as List; + final AssetResourceManagerBytesListener arg_pigeon_instance = + args[0]! as AssetResourceManagerBytesListener; + final String? arg_error = args[1] as String?; + try { + (onCompletion ?? arg_pigeon_instance.onCompletion).call(arg_pigeon_instance, arg_error); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString()), + ); + } + }); + } + } + } + + Future openRead(String localIdentifier) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecAssetResourceManagerBytesListener; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.openRead'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + this, + localIdentifier, + ]); + final pigeonVar_replyList = await pigeonVar_sendFuture as List?; + + final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: false, + ); + return pigeonVar_replyValue! as bool; + } + + @override + AssetResourceManagerBytesListener pigeon_copy() { + return AssetResourceManagerBytesListener.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + onDataReceived: onDataReceived, + onCompletion: onCompletion, + ); + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index d624dc9cceac..3a1148309dd9 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -14,6 +14,7 @@ import 'package:flutter/foundation.dart'; import 'package:objective_c/objective_c.dart'; import 'package:path/path.dart' as path; +import 'cross_file_darwin_apis.g.dart'; import 'ffi_bindings.g.dart'; import 'security_scoped_resource.dart'; @@ -202,22 +203,17 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile assert(start == null || start >= 0); assert(end == null || end >= (start ?? 0)); - if (_tryGetAssetResource(identifier: params.uri) case final PHAssetResource resource) { - final PHAssetResourceManager resourceManager = PHAssetResourceManager.defaultManager(); - + if (_tryGetAssetResource(identifier: params.uri) != null) { final streamController = StreamController(); var currentByteIndex = 0; - void dataReceivedHandler(NSData data) { - final Uint8List bytes = _extractBytesToUint8List(data); - - runOnPlatformThread(() { + final bytesListener = AssetResourceManagerBytesListener( + onDataReceived: (_, Uint8List bytes) { final int newByteIndex = currentByteIndex + bytes.length; final int startOrZero = start ?? 0; if (end == null) { if (currentByteIndex >= startOrZero) { - print('adding ${bytes.length} bytes. starting with ${bytes[0]} ${bytes[1]}'); streamController.add(bytes); } else { if (newByteIndex > startOrZero) { @@ -245,30 +241,28 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } currentByteIndex = newByteIndex; - }); - } - - void completionHandler(NSError? error) { - runOnPlatformThread(() { + }, + onCompletion: (_, String? error) { if (error != null) { - streamController.addError(Exception(error.localizedDescription.toDartString())); + streamController.addError(Exception(error)); } - print('end stream'); - return streamController.close(); - }); - } - - resourceManager.requestDataForAssetResource( - resource, - dataReceivedHandler: ObjCBlock_ffiVoid_NSData.listener(dataReceivedHandler), - completionHandler: ObjCBlock_ffiVoid_NSError.listener(completionHandler), + streamController.close(); + }, ); + bytesListener.openRead(params.uri).then((bool canRead) { + if (!canRead) { + streamController.addError( + Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), + ); + streamController.close(); + } + }); return streamController.stream; } - throw Error(); + throw Exception('Failed to retrieve PHAssetResource for asset with identifier: ${params.uri}'); } @override diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index fe938f5f0877..a7cb90cf47fa 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -9,49 +9,18 @@ import 'package:pigeon/pigeon.dart'; @ConfigurePigeon( PigeonOptions( dartOut: 'lib/src/cross_file_darwin_apis.g.dart', - swiftOut: - 'darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift', + swiftOut: 'darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift', copyrightHeader: 'pigeons/copyright.txt', ), ) /// Api for getting access to file information. -@HostApi() -abstract class CrossFileDarwinApi { - /// In an app that has adopted App Sandbox, makes the resource pointed to by a - /// security-scoped URL available to the app. - bool startAccessingSecurityScopedResource(String url); +@ProxyApi() +abstract class AssetResourceManagerBytesListener { + AssetResourceManagerBytesListener(); - /// In an app that adopts App Sandbox, revokes access to the resource pointed - /// to by a security-scoped URL. - void stopAccessingSecurityScopedResource(String url); + late final void Function(Uint8List bytes) onDataReceived; - /// Whether the native FileManager is able to read a specified file. - bool isReadableFile(String url); - // - // /// Date and time when the resource was last modified, if the information is - // /// available. - // /// - // /// Returns null if file doesn't exist or information is not available. - // @async - // int? lastModified(String identifier); - // - // /// The length of the data represented by this uri, in bytes. - // /// - // /// Returns null if file doesn't exist or information is not available. - // //Future length(String identifier); - // - // /// Reads the entire resource contents as a list of bytes. - // /// - // /// Platforms may throw an exception if there is an error opening or reading - // /// the resource. - // @async - // Uint8List readAsBytes(String identifier); - // - // /// The name of the resource represented by this object. - // /// - // /// The path is excluded from this value. - // /// - // /// Returns null if file doesn't exist or information is not available. - // @async - // String? name(String identifier); + late final void Function(String? error) onCompletion; + + bool openRead(String localIdentifier); } From eb28858f3ba286b95f2320fd24f99c4255c61818 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 11:05:38 -0400 Subject: [PATCH 297/398] proxy api for byte reading --- .../darwin/cross_file_darwin/Package.swift | 18 +- .../AssetResourceManagerBytesListener.swift | 39 ++++ .../CrossFileDarwinApis.g.swift | 211 ++++++++++++------ .../CrossFileDarwinPlugin.swift | 19 +- .../cross_file_darwin/ProxyAPIRegistrar.swift | 55 +++++ .../AssetResourceReaderAPIDelegate.swift | 63 ++++++ .../CrossFileDarwinApiImpl.swift | 77 ------- .../cross_file_darwin_objc/ffi_bindings.g.m | 172 +++++++------- .../cross_file_darwin/example/lib/main.dart | 20 +- .../lib/src/cross_file_darwin.dart | 4 +- .../lib/src/cross_file_darwin_apis.g.dart | 85 +++---- ...darwin_scoped_storage_cross_directory.dart | 34 +-- .../src/darwin_scoped_storage_cross_file.dart | 9 +- .../pigeons/cross_file_darwin_apis.dart | 4 +- ...n_scoped_storage_cross_directory_test.dart | 20 +- ...ed_storage_cross_directory_test.mocks.dart | 3 +- ...darwin_scoped_storage_cross_file_test.dart | 8 +- ..._scoped_storage_cross_file_test.mocks.dart | 3 +- 18 files changed, 483 insertions(+), 361 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift index 8ce7b95081f6..d83ea024bece 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift @@ -18,21 +18,21 @@ let package = Package( dependencies: [], targets: [ .target( - name: "cross_file_darwin", - dependencies: [ - "cross_file_darwin_objc" - ], - resources: [ - .process("Resources") - ] + name: "cross_file_darwin", + dependencies: [ + "cross_file_darwin_objc" + ], + resources: [ + .process("Resources") + ] ), .target( name: "cross_file_darwin_objc", dependencies: [], sources: [ - "ffi_bindings.g.m", + "ffi_bindings.g.m" ], publicHeadersPath: "include", - ) + ), ] ) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift new file mode 100644 index 000000000000..d290eed7b315 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Photos + +class AssetResourceReader { + var delegate: AssetResourceReaderDelegate? + + func openRead(localIdentifier: String) -> Bool { + let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) + if let asset = assets.firstObject { + let resources = PHAssetResource.assetResources(for: asset) + if let resource = resources.first { + let resourceManager = PHAssetResourceManager.default() + + let options = PHAssetResourceRequestOptions() + options.isNetworkAccessAllowed = true + + resourceManager.requestData(for: resource, options: options) { data in + DispatchQueue.main.async { + self.delegate?.onDataReceived(reader: self, bytes: data) + } + } completionHandler: { error in + DispatchQueue.main.async { + self.delegate?.onCompletion(reader: self, error: error?.localizedDescription) + } + } + } + } + + return false + } +} + +protocol AssetResourceReaderDelegate { + func onDataReceived(reader: AssetResourceReader, bytes: Data) + func onCompletion(reader: AssetResourceReader, error: String?) +} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 6dade73fe2db..f147905c994e 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -59,7 +59,9 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -77,7 +79,6 @@ protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { func onDeinit(identifier: Int64) } - // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -93,14 +94,18 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, + delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( + identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = + objc_getAssociatedObject(instance, associatedObjectKey) + as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -112,7 +117,6 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } - /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -216,7 +220,8 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -297,7 +302,6 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } - private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -310,9 +314,15 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, + instanceManager: CrossFileDarwinApisPigeonInstanceManager? + ) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -327,7 +337,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -343,9 +355,13 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -363,9 +379,10 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } } protocol CrossFileDarwinApisPigeonProxyApiDelegate { - /// An implementation of [PigeonApiAssetResourceManagerBytesListener] used to add a new Dart instance of - /// `AssetResourceManagerBytesListener` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiAssetResourceManagerBytesListener(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceManagerBytesListener + /// An implementation of [PigeonApiAssetResourceReader] used to add a new Dart instance of + /// `AssetResourceReader` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiAssetResourceReader } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -378,12 +395,15 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + private class InstanceManagerApiFinalizerDelegate: + CrossFileDarwinApisPigeonInternalFinalizerDelegate + { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -397,7 +417,9 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + init( + binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + ) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -406,18 +428,25 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiAssetResourceManagerBytesListener.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceManagerBytesListener(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiAssetResourceReader.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) - PigeonApiAssetResourceManagerBytesListener.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) + PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: + FlutterStandardReaderWriter +{ unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: + CrossFileDarwinApisPigeonCodecReader + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -441,7 +470,9 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: + CrossFileDarwinApisPigeonCodecWriter + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -450,24 +481,26 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + { super.writeValue(value) return } - - if let instance = value as? AssetResourceManagerBytesListener { - pigeonRegistrar.apiDelegate.pigeonApiAssetResourceManagerBytesListener(pigeonRegistrar).pigeonNewInstance( + if let instance = value as? AssetResourceReader { + pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReader(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -485,11 +518,13 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( + data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( + data: data, pigeonRegistrar: pigeonRegistrar) } } @@ -510,41 +545,58 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } -protocol PigeonApiDelegateAssetResourceManagerBytesListener { - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceManagerBytesListener) throws -> AssetResourceManagerBytesListener - func openRead(pigeonApi: PigeonApiAssetResourceManagerBytesListener, pigeonInstance: AssetResourceManagerBytesListener, localIdentifier: String) throws -> Bool +protocol PigeonApiDelegateAssetResourceReader { + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws + -> AssetResourceReader + func openRead( + pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, + localIdentifier: String + ) throws -> Bool } -protocol PigeonApiProtocolAssetResourceManagerBytesListener { - func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) - func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, error errorArg: String?, completion: @escaping (Result) -> Void) +protocol PigeonApiProtocolAssetResourceReader { + func onDataReceived( + pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, + completion: @escaping (Result) -> Void) + func onCompletion( + pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, + completion: @escaping (Result) -> Void) } -final class PigeonApiAssetResourceManagerBytesListener: PigeonApiProtocolAssetResourceManagerBytesListener { +final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateAssetResourceManagerBytesListener - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateAssetResourceManagerBytesListener) { + let pigeonDelegate: PigeonApiDelegateAssetResourceReader + init( + pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateAssetResourceReader + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceManagerBytesListener?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.pigeon_defaultConstructor", binaryMessenger: binaryMessenger, codec: codec) + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { pigeonDefaultConstructorChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( -try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), -withIdentifier: pigeonIdentifierArg) + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -553,14 +605,17 @@ withIdentifier: pigeonIdentifierArg) } else { pigeonDefaultConstructorChannel.setMessageHandler(nil) } - let openReadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.openRead", binaryMessenger: binaryMessenger, codec: codec) + let openReadChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { openReadChannel.setMessageHandler { message, reply in let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! AssetResourceManagerBytesListener + let pigeonInstanceArg = args[0] as! AssetResourceReader let localIdentifierArg = args[1] as! String do { - let result = try api.pigeonDelegate.openRead(pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) + let result = try api.pigeonDelegate.openRead( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -571,25 +626,32 @@ withIdentifier: pigeonIdentifierArg) } } - ///Creates a Dart instance of AssetResourceManagerBytesListener and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: AssetResourceManagerBytesListener, completion: @escaping (Result) -> Void) { + ///Creates a Dart instance of AssetResourceReader and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { + } else { completion( .failure( PigeonError( code: "new-instance-error", - message: "Error: Attempting to create a new Dart instance of AssetResourceManagerBytesListener, but the class has a nonnull callback method.", details: ""))) + message: + "Error: Attempting to create a new Dart instance of AssetResourceReader, but the class has a nonnull callback method.", + details: ""))) } } - func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { + func onDataReceived( + pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -597,18 +659,22 @@ withIdentifier: pigeonIdentifierArg) code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: "Callback to `AssetResourceManagerBytesListener.onDataReceived` failed because native instance was not in the instance manager.", details: ""))) + message: + "Callback to `AssetResourceReader.onDataReceived` failed because native instance was not in the instance manager.", + details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onDataReceived" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, bytesArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -625,7 +691,10 @@ withIdentifier: pigeonIdentifierArg) } } - func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceManagerBytesListener, error errorArg: String?, completion: @escaping (Result) -> Void) { + func onCompletion( + pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -633,18 +702,22 @@ withIdentifier: pigeonIdentifierArg) code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: "Callback to `AssetResourceManagerBytesListener.onCompletion` failed because native instance was not in the instance manager.", details: ""))) + message: + "Callback to `AssetResourceReader.onCompletion` failed because native instance was not in the instance manager.", + details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onCompletion" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, errorArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift index 7a32422006bb..429910764cc1 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift @@ -11,6 +11,14 @@ #endif public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { + var proxyApiRegistrar: ProxyAPIRegistrar? + + init(binaryMessenger: FlutterBinaryMessenger) { + proxyApiRegistrar = ProxyAPIRegistrar( + binaryMessenger: binaryMessenger) + proxyApiRegistrar?.setUp() + } + public static func register(with registrar: FlutterPluginRegistrar) { #if os(iOS) let messenger = registrar.messenger() @@ -18,6 +26,15 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { let messenger = registrar.messenger #endif - CrossFileDarwinApiSetup.setUp(binaryMessenger: messenger, api: CrossFileDarwinApiImpl()) + let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger) + + registrar.publish(plugin) + } + + public func detachFromEngine(for registrar: FlutterPluginRegistrar) { + proxyApiRegistrar?.ignoreCallsToDart = true + proxyApiRegistrar?.tearDown() + try? proxyApiRegistrar?.instanceManager.removeAllObjects() + proxyApiRegistrar = nil } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift new file mode 100644 index 000000000000..6118b618d1e7 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift @@ -0,0 +1,55 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +#if os(iOS) + import Flutter + import UIKit +#elseif os(macOS) + import FlutterMacOS + import Foundation +#else + #error("Unsupported platform.") +#endif + +open class ProxyAPIRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar { + init( + binaryMessenger: FlutterBinaryMessenger, + ) { + super.init(binaryMessenger: binaryMessenger, apiDelegate: ProxyAPIDelegate()) + } + + // Log when a Flutter method receives an error from Dart. + func logFlutterMethodFailure(_ error: PigeonError, methodName: String) { + NSLog( + "\(String(describing: error)): Error returned from calling \(methodName): \(String(describing: error.message))" + ) + NSLog("%@", Thread.callStackSymbols.joined(separator: "\n")) + } + + /// Handles calling a Flutter method on the main thread. + func dispatchOnMainThread( + execute work: + @escaping ( + _ onFailure: @escaping (_ methodName: String, _ error: PigeonError) -> Void + ) -> Void + ) { + DispatchQueue.main.async { + work { methodName, error in + self.logFlutterMethodFailure(error, methodName: methodName) + } + } + } +} + +/// Implementation of `CrossFileDarwinApisPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation. +class ProxyAPIDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { + func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiAssetResourceReader + { + return PigeonApiAssetResourceReader( + pigeonRegistrar: registrar, delegate: AssetResourceReaderAPIDelegate()) + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift new file mode 100644 index 000000000000..5f746ee3b9e3 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Foundation + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +private class AssetResourceReaderDelegateImpl: NSObject, AssetResourceReaderDelegate { + let api: PigeonApiProtocolAssetResourceReader + unowned let registrar: ProxyAPIRegistrar + + init(api: PigeonApiProtocolAssetResourceReader, registrar: ProxyAPIRegistrar) { + self.api = api + self.registrar = registrar + } + + func onDataReceived(reader: AssetResourceReader, bytes: Data) { + let data = FlutterStandardTypedData(bytes: bytes) + registrar.dispatchOnMainThread { onFailure in + self.api.onDataReceived(pigeonInstance: reader, bytes: data) { result in + if case .failure(let error) = result { + onFailure("AssetResourceReaderDelegate.onDataReceived", error) + } + } + } + } + + func onCompletion(reader: AssetResourceReader, error: String?) { + registrar.dispatchOnMainThread { onFailure in + self.api.onCompletion(pigeonInstance: reader, error: error) { result in + if case .failure(let error) = result { + onFailure("AssetResourceReaderDelegate.onCompletion", error) + } + } + } + } +} + +/// Implementation of `PigeonApiDelegateAssetResourceReader`. +class AssetResourceReaderAPIDelegate: PigeonApiDelegateAssetResourceReader { + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws + -> AssetResourceReader + { + let reader = AssetResourceReader() + reader.delegate = AssetResourceReaderDelegateImpl( + api: pigeonApi, registrar: pigeonApi.pigeonRegistrar as! ProxyAPIRegistrar) + return reader + } + + func openRead( + pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, + localIdentifier: String + ) throws -> Bool { + return pigeonInstance.openRead(localIdentifier: localIdentifier) + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift deleted file mode 100644 index c6b6424b9bd3..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/CrossFileDarwinApiImpl.swift +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation -import Photos - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Implementation of `CrossFileDarwinApi`. -class CrossFileDarwinApiImpl: CrossFileDarwinApi { - func startAccessingSecurityScopedResource(url: String) throws -> Bool { - return URL(string: url)!.startAccessingSecurityScopedResource() - } - - func stopAccessingSecurityScopedResource(url: String) throws { - URL(string: url)!.stopAccessingSecurityScopedResource() - } - - func isReadableFile(url: String) throws -> Bool { - return FileManager.default.isReadableFile(atPath: URL(string: url)!.path) - } - // - // func lastModified(identifier: String, completion: @escaping (Result) -> Void) { - // let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) - // if let asset = fetchResult.firstObject { - // if let modificationDate = asset.modificationDate { - // completion(.success(Int64(asset.modificationDate.timeIntervalSince1970 * 1000.0).rounded())) - // } else { - // completion(.success(nil)) - // } - // } else { - // completion(.success(nil)) - // } - // } - // - // func readAsBytes( - // identifier: String, completion: @escaping (Result) -> Void - // ) { - // let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) - // if let asset = fetchResult.firstObject { - // // 3. Request the actual image data from the asset - // let manager = PHImageManager.default() - // let options = PHImageRequestOptions() - // options.isNetworkAccessAllowed = true // In case it's stored in iCloud - // - // manager.requestImageDataAndOrientation( - // for: asset, options: options, - // ) { imageData, orientation, info in - // - // if let imageData = image { - // completion(.success(FlutterStandardTypedData(bytes: imageData))) - // } else { - // completion(.success(nil)) - // } - // } - // } else { - // completion(.success(nil)) - // } - // } - // - // func name(identifier: String, completion: @escaping (Result) -> Void) { - // let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [identifier], options: nil) - // if let asset = fetchResult.firstObject { - // let resources = PHAssetResource.assetResources(for: asset) - // completion(.success(resources.first!.originalFilename)) - // } else { - // completion(.success(nil)) - // } - // } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index 8cc5eb341fa2..3d5f3bb2782b 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -1,7 +1,7 @@ -#include #import -#import #import +#import +#include #if !__has_feature(objc_arc) #error "This file must be compiled with ARC enabled" @@ -12,10 +12,10 @@ typedef struct { int64_t version; - void* (*newWaiter)(void); - void (*awaitWaiter)(void*); - void* (*currentIsolate)(void); - void (*enterIsolate)(void*); + void *(*newWaiter)(void); + void (*awaitWaiter)(void *); + void *(*currentIsolate)(void); + void (*enterIsolate)(void *); void (*exitIsolate)(void); int64_t (*getMainPortId)(void); bool (*getCurrentThreadOwnsIsolate)(int64_t); @@ -23,99 +23,115 @@ id objc_retainBlock(id); -#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ - assert(ctx->version >= 1); \ - void* targetIsolate = ctx->currentIsolate(); \ - int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ - return BLOCK_SIG { \ - void* currentIsolate = ctx->currentIsolate(); \ - bool mayEnterIsolate = \ - currentIsolate == NULL && \ - ctx->getCurrentThreadOwnsIsolate != NULL && \ - ctx->getCurrentThreadOwnsIsolate(targetPort); \ - if (currentIsolate == targetIsolate || mayEnterIsolate) { \ - if (mayEnterIsolate) { \ - ctx->enterIsolate(targetIsolate); \ - } \ - INVOKE_DIRECT; \ - if (mayEnterIsolate) { \ - ctx->exitIsolate(); \ - } \ - } else { \ - void* waiter = ctx->newWaiter(); \ - INVOKE_LISTENER; \ - ctx->awaitWaiter(waiter); \ - } \ +#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ + assert(ctx->version >= 1); \ + void *targetIsolate = ctx->currentIsolate(); \ + int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ + return BLOCK_SIG { \ + void *currentIsolate = ctx->currentIsolate(); \ + bool mayEnterIsolate = currentIsolate == NULL && ctx->getCurrentThreadOwnsIsolate != NULL && \ + ctx->getCurrentThreadOwnsIsolate(targetPort); \ + if (currentIsolate == targetIsolate || mayEnterIsolate) { \ + if (mayEnterIsolate) { \ + ctx->enterIsolate(targetIsolate); \ + } \ + INVOKE_DIRECT; \ + if (mayEnterIsolate) { \ + ctx->exitIsolate(); \ + } \ + } else { \ + void *waiter = ctx->newWaiter(); \ + INVOKE_LISTENER; \ + ctx->awaitWaiter(waiter); \ + } \ }; - -typedef void (^_ListenerTrampoline)(id arg0, id arg1); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _NativeLibrary_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline)(id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline +_NativeLibrary_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1) { objc_retainBlock(block); - block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + block((__bridge id)(__bridge_retained void *)(arg0), + (__bridge id)(__bridge_retained void *)(arg1)); }; } -typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _NativeLibrary_wrapBlockingBlock_pfv6jd( - _BlockingTrampoline block, _BlockingTrampoline listenerBlock, - DOBJC_Context* ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1), { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); - }, { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); - }); +typedef void (^_BlockingTrampoline)(void *waiter, id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline +_NativeLibrary_wrapBlockingBlock_pfv6jd(_BlockingTrampoline block, + _BlockingTrampoline listenerBlock, + DOBJC_Context *ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL( + ctx, ^void(id arg0, id arg1), + { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void *)(arg0), + (__bridge id)(__bridge_retained void *)(arg1)); + }, + { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void *)(arg0), + (__bridge id)(__bridge_retained void *)(arg1)); + }); } -typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _NativeLibrary_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_1 +_NativeLibrary_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { objc_retainBlock(block); - block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + block((__bridge id)(__bridge_retained void *)(arg0), + (__bridge id)(__bridge_retained void *)(arg1), arg2, + (__bridge id)(__bridge_retained void *)(arg3)); }; } -typedef void (^_BlockingTrampoline_1)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _NativeLibrary_wrapBlockingBlock_10c3wkj( - _BlockingTrampoline_1 block, _BlockingTrampoline_1 listenerBlock, - DOBJC_Context* ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); - }, { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); - }); +typedef void (^_BlockingTrampoline_1)(void *waiter, id arg0, id arg1, + CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_1 +_NativeLibrary_wrapBlockingBlock_10c3wkj(_BlockingTrampoline_1 block, + _BlockingTrampoline_1 listenerBlock, + DOBJC_Context *ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL( + ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), + { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void *)(arg0), + (__bridge id)(__bridge_retained void *)(arg1), arg2, + (__bridge id)(__bridge_retained void *)(arg3)); + }, + { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void *)(arg0), + (__bridge id)(__bridge_retained void *)(arg1), arg2, + (__bridge id)(__bridge_retained void *)(arg3)); + }); } -typedef void (^_ListenerTrampoline_2)(id arg0); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _NativeLibrary_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline_2)(id arg0); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_2 +_NativeLibrary_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { return ^void(id arg0) { objc_retainBlock(block); - block((__bridge id)(__bridge_retained void*)(arg0)); + block((__bridge id)(__bridge_retained void *)(arg0)); }; } -typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _NativeLibrary_wrapBlockingBlock_xtuoz7( - _BlockingTrampoline_2 block, _BlockingTrampoline_2 listenerBlock, - DOBJC_Context* ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0), { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void*)(arg0)); - }, { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0)); - }); +typedef void (^_BlockingTrampoline_2)(void *waiter, id arg0); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_2 +_NativeLibrary_wrapBlockingBlock_xtuoz7(_BlockingTrampoline_2 block, + _BlockingTrampoline_2 listenerBlock, + DOBJC_Context *ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL( + ctx, ^void(id arg0), + { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void *)(arg0)); + }, + { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void *)(arg0)); + }); } #undef BLOCKING_BLOCK_IMPL diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 4c4f58a8a56c..7c272a16c3ed 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -72,10 +72,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), + appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -106,11 +103,7 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay({ - super.key, - required this.filename, - required this.fileContents, - }); + const TextDisplay({super.key, required this.filename, required this.fileContents}); /// The name of the file. final String filename; @@ -122,14 +115,9 @@ class TextDisplay extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( title: Text(filename), - content: Scrollbar( - child: SingleChildScrollView(child: Text(fileContents)), - ), + content: Scrollbar(child: SingleChildScrollView(child: Text(fileContents))), actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), + TextButton(child: const Text('Close'), onPressed: () => Navigator.pop(context)), ], ); } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index b0eca993685f..a6d08b9211d5 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -15,9 +15,7 @@ base class CrossFileDarwin extends CrossFileIO { /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileDarwin(); - ffi.DynamicLibrary.open( - '/System/Library/Frameworks/Photos.framework/Photos', - ); + ffi.DynamicLibrary.open('/System/Library/Frameworks/Photos.framework/Photos'); } /// Whether the current implementation of `cross_file` is [CrossFileDarwin]. diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 6d6c486e732d..f17fe10612c0 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -58,18 +58,16 @@ List wrapResponse({Object? result, PlatformException? error, bool empty /// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. @visibleForTesting class PigeonOverrides { - /// Overrides [AssetResourceManagerBytesListener.new]. - static AssetResourceManagerBytesListener Function({ - required void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes) - onDataReceived, - required void Function(AssetResourceManagerBytesListener pigeon_instance, String? error) - onCompletion, + /// Overrides [AssetResourceReader.new]. + static AssetResourceReader Function({ + required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, + required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, })? - assetResourceManagerBytesListener_new; + assetResourceReader_new; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { - assetResourceManagerBytesListener_new = null; + assetResourceReader_new = null; } } @@ -179,9 +177,7 @@ class PigeonInstanceManager { }, ); _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - AssetResourceManagerBytesListener.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + AssetResourceReader.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -433,22 +429,20 @@ class _PigeonCodec extends StandardMessageCodec { } /// Api for getting access to file information. -class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass { - factory AssetResourceManagerBytesListener({ +class AssetResourceReader extends PigeonInternalProxyApiBaseClass { + factory AssetResourceReader({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - required void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes) - onDataReceived, - required void Function(AssetResourceManagerBytesListener pigeon_instance, String? error) - onCompletion, + required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, + required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, }) { - if (PigeonOverrides.assetResourceManagerBytesListener_new != null) { - return PigeonOverrides.assetResourceManagerBytesListener_new!( + if (PigeonOverrides.assetResourceReader_new != null) { + return PigeonOverrides.assetResourceReader_new!( onDataReceived: onDataReceived, onCompletion: onCompletion, ); } - return AssetResourceManagerBytesListener.pigeon_new( + return AssetResourceReader.pigeon_new( pigeon_binaryMessenger: pigeon_binaryMessenger, pigeon_instanceManager: pigeon_instanceManager, onDataReceived: onDataReceived, @@ -457,18 +451,17 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass } @protected - AssetResourceManagerBytesListener.pigeon_new({ + AssetResourceReader.pigeon_new({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, required this.onDataReceived, required this.onCompletion, }) { final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceManagerBytesListener; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.pigeon_defaultConstructor'; + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -484,19 +477,19 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass }(); } - /// Constructs [AssetResourceManagerBytesListener] without creating the associated native object. + /// Constructs [AssetResourceReader] without creating the associated native object. /// /// This should only be used by subclasses created by this library or to /// create copies for an [PigeonInstanceManager]. @protected - AssetResourceManagerBytesListener.pigeon_detached({ + AssetResourceReader.pigeon_detached({ super.pigeon_binaryMessenger, super.pigeon_instanceManager, required this.onDataReceived, required this.onCompletion, }); - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceManagerBytesListener = + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceReader = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); /// Callback method. @@ -509,8 +502,8 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass /// /// ```dart /// final WeakReference weakMyVariable = WeakReference(myVariable); - /// final AssetResourceManagerBytesListener instance = AssetResourceManagerBytesListener( - /// onDataReceived: (AssetResourceManagerBytesListener pigeon_instance, ...) { + /// final AssetResourceReader instance = AssetResourceReader( + /// onDataReceived: (AssetResourceReader pigeon_instance, ...) { /// print(weakMyVariable?.target); /// }, /// ); @@ -518,8 +511,7 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes) - onDataReceived; + final void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived; /// Callback method. /// @@ -531,8 +523,8 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass /// /// ```dart /// final WeakReference weakMyVariable = WeakReference(myVariable); - /// final AssetResourceManagerBytesListener instance = AssetResourceManagerBytesListener( - /// onCompletion: (AssetResourceManagerBytesListener pigeon_instance, ...) { + /// final AssetResourceReader instance = AssetResourceReader( + /// onCompletion: (AssetResourceReader pigeon_instance, ...) { /// print(weakMyVariable?.target); /// }, /// ); @@ -540,16 +532,14 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function(AssetResourceManagerBytesListener pigeon_instance, String? error) - onCompletion; + final void Function(AssetResourceReader pigeon_instance, String? error) onCompletion; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - void Function(AssetResourceManagerBytesListener pigeon_instance, Uint8List bytes)? - onDataReceived, - void Function(AssetResourceManagerBytesListener pigeon_instance, String? error)? onCompletion, + void Function(AssetResourceReader pigeon_instance, Uint8List bytes)? onDataReceived, + void Function(AssetResourceReader pigeon_instance, String? error)? onCompletion, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( pigeon_instanceManager ?? PigeonInstanceManager.instance, @@ -557,7 +547,7 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onDataReceived', + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived', pigeonChannelCodec, binaryMessenger: binaryMessenger, ); @@ -566,8 +556,7 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; - final AssetResourceManagerBytesListener arg_pigeon_instance = - args[0]! as AssetResourceManagerBytesListener; + final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; final Uint8List arg_bytes = args[1]! as Uint8List; try { (onDataReceived ?? arg_pigeon_instance.onDataReceived).call( @@ -588,7 +577,7 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.onCompletion', + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion', pigeonChannelCodec, binaryMessenger: binaryMessenger, ); @@ -597,8 +586,7 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; - final AssetResourceManagerBytesListener arg_pigeon_instance = - args[0]! as AssetResourceManagerBytesListener; + final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; final String? arg_error = args[1] as String?; try { (onCompletion ?? arg_pigeon_instance.onCompletion).call(arg_pigeon_instance, arg_error); @@ -616,11 +604,10 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass } Future openRead(String localIdentifier) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceManagerBytesListener; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceManagerBytesListener.openRead'; + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, @@ -641,8 +628,8 @@ class AssetResourceManagerBytesListener extends PigeonInternalProxyApiBaseClass } @override - AssetResourceManagerBytesListener pigeon_copy() { - return AssetResourceManagerBytesListener.pigeon_detached( + AssetResourceReader pigeon_copy() { + return AssetResourceReader.pigeon_detached( pigeon_binaryMessenger: pigeon_binaryMessenger, pigeon_instanceManager: pigeon_instanceManager, onDataReceived: onDataReceived, diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index cfdcf01ef436..90723ce091e1 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -23,9 +23,8 @@ sealed class DarwinScopedStorageXDirectoryCreationParams /// Constructs a [DarwinScopedStorageXDirectoryCreationParams] with a security /// scoped uri. - factory DarwinScopedStorageXDirectoryCreationParams.securityScoped({ - required String uri, - }) => SecurityScopedDarwinScopedStorageXDirectoryCreationParams(uri: uri); + factory DarwinScopedStorageXDirectoryCreationParams.securityScoped({required String uri}) => + SecurityScopedDarwinScopedStorageXDirectoryCreationParams(uri: uri); } /// Creation parameters for [SecurityScopedDarwinScopedStorageXDirectory]. @@ -33,17 +32,12 @@ sealed class DarwinScopedStorageXDirectoryCreationParams base class SecurityScopedDarwinScopedStorageXDirectoryCreationParams extends DarwinScopedStorageXDirectoryCreationParams { /// Constructs a [SecurityScopedDarwinScopedStorageXDirectoryCreationParams]. - const SecurityScopedDarwinScopedStorageXDirectoryCreationParams({ - required super.uri, - }); + const SecurityScopedDarwinScopedStorageXDirectoryCreationParams({required super.uri}); } /// Base implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. -sealed class DarwinScopedStorageXDirectory - extends PlatformScopedStorageXDirectory { - factory DarwinScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams params, - ) { +sealed class DarwinScopedStorageXDirectory extends PlatformScopedStorageXDirectory { + factory DarwinScopedStorageXDirectory(PlatformScopedStorageXDirectoryCreationParams params) { return SecurityScopedDarwinScopedStorageXDirectory(params); } @@ -53,8 +47,7 @@ sealed class DarwinScopedStorageXDirectory /// Implementation of [DarwinScopedStorageXDirectory] for interacting with a /// security-scoped URL. -base class SecurityScopedDarwinScopedStorageXDirectory - extends DarwinScopedStorageXDirectory +base class SecurityScopedDarwinScopedStorageXDirectory extends DarwinScopedStorageXDirectory with SecurityScopedDarwinScopedStorageXDirectoryExtension { /// Constructs a [SecurityScopedDarwinScopedStorageXDirectory]. SecurityScopedDarwinScopedStorageXDirectory(super.params) : super._() { @@ -76,11 +69,8 @@ base class SecurityScopedDarwinScopedStorageXDirectory @override late final SecurityScopedDarwinScopedStorageXDirectoryCreationParams params = super.params is SecurityScopedDarwinScopedStorageXDirectoryCreationParams - ? super.params - as SecurityScopedDarwinScopedStorageXDirectoryCreationParams - : SecurityScopedDarwinScopedStorageXDirectoryCreationParams( - uri: super.params.uri, - ); + ? super.params as SecurityScopedDarwinScopedStorageXDirectoryCreationParams + : SecurityScopedDarwinScopedStorageXDirectoryCreationParams(uri: super.params.uri); @override SecurityScopedDarwinScopedStorageXDirectoryExtension? get extension => this; @@ -100,9 +90,7 @@ base class SecurityScopedDarwinScopedStorageXDirectory ); case final File file: yield DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams.securityScoped( - uri: file.uri.toString(), - ), + DarwinScopedStorageXFileCreationParams.securityScoped(uri: file.uri.toString()), ); } } @@ -136,6 +124,4 @@ base class SecurityScopedDarwinScopedStorageXDirectory /// Provides platform specific features for /// [SecurityScopedDarwinScopedStorageXDirectory]. mixin SecurityScopedDarwinScopedStorageXDirectoryExtension - implements - PlatformScopedStorageXDirectoryExtension, - SecurityScopedResource {} + implements PlatformScopedStorageXDirectoryExtension, SecurityScopedResource {} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 3a1148309dd9..c23c42f333bd 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -207,7 +207,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final streamController = StreamController(); var currentByteIndex = 0; - final bytesListener = AssetResourceManagerBytesListener( + final bytesListener = AssetResourceReader( onDataReceived: (_, Uint8List bytes) { final int newByteIndex = currentByteIndex + bytes.length; final int startOrZero = start ?? 0; @@ -336,13 +336,6 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); final ObjCObject? firstObject = resources.firstObject; - print('cfd: ${resources.count}'); - for (var index = 0; index < resources.count; index++) { - final resource = PHAssetResource.as(resources.objectAtIndex(index)); - print('cfd: ${resource.type}'); - print('cfd: ${resource.contentType.preferredMIMEType}'); - } - if (firstObject != null) { return PHAssetResource.as(firstObject); } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index a7cb90cf47fa..ff115172d561 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -15,8 +15,8 @@ import 'package:pigeon/pigeon.dart'; ) /// Api for getting access to file information. @ProxyApi() -abstract class AssetResourceManagerBytesListener { - AssetResourceManagerBytesListener(); +abstract class AssetResourceReader { + AssetResourceReader(); late final void Function(Uint8List bytes) onDataReceived; diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart index 121389ffcaab..62711caf6e48 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart @@ -15,9 +15,7 @@ import 'package:path/path.dart' as path; import 'darwin_scoped_storage_cross_directory_test.mocks.dart'; -final Directory testDirectory = Directory( - path.join(Directory.current.path, 'test'), -); +final Directory testDirectory = Directory(path.join(Directory.current.path, 'test')); @GenerateMocks([CrossFileDarwinApi]) void main() { @@ -29,9 +27,7 @@ void main() { test('exists', () async { final directory = PlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams( - uri: testDirectory.uri.toString(), - ), + PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.uri.toString()), ); expect(await directory.exists(), testDirectory.existsSync()); @@ -39,18 +35,14 @@ void main() { test('list', () async { final directory = PlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams( - uri: testDirectory.uri.toString(), - ), + PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.uri.toString()), ); expect( (await directory.list(ListParams()).toList()).map( (PlatformXEntity entity) => entity.params.uri, ), - (await testDirectory.list().toList()).map( - (FileSystemEntity entity) => entity.uri.toString(), - ), + (await testDirectory.list().toList()).map((FileSystemEntity entity) => entity.uri.toString()), ); }); @@ -71,9 +63,7 @@ void main() { final mockApi = MockCrossFileDarwinApi(); final uri = testDirectory.uri.toString(); const result = true; - when( - mockApi.startAccessingSecurityScopedResource(uri), - ).thenAnswer((_) async => result); + when(mockApi.startAccessingSecurityScopedResource(uri)).thenAnswer((_) async => result); final directory = DarwinScopedStorageXDirectory( DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart index de0293c07512..ce5b2b295db8 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart @@ -27,8 +27,7 @@ import 'package:mockito/src/dummies.dart' as _i3; /// A class which mocks [CrossFileDarwinApi]. /// /// See the documentation for Mockito's code generation for more information. -class MockCrossFileDarwinApi extends _i1.Mock - implements _i2.CrossFileDarwinApi { +class MockCrossFileDarwinApi extends _i1.Mock implements _i2.CrossFileDarwinApi { MockCrossFileDarwinApi() { _i1.throwOnMissingStub(this); } diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart index 1dd0d30ae8ec..bd2aa1630307 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart @@ -15,9 +15,7 @@ import 'package:path/path.dart' as path; import 'darwin_scoped_storage_cross_file_test.mocks.dart'; -final File testFile = File( - path.join(Directory.current.path, 'test', 'test_file.txt'), -); +final File testFile = File(path.join(Directory.current.path, 'test', 'test_file.txt')); @GenerateMocks([CrossFileDarwinApi]) void main() { @@ -100,9 +98,7 @@ void main() { final mockApi = MockCrossFileDarwinApi(); final uri = testFile.uri.toString(); const result = true; - when( - mockApi.startAccessingSecurityScopedResource(uri), - ).thenAnswer((_) async => result); + when(mockApi.startAccessingSecurityScopedResource(uri)).thenAnswer((_) async => result); final file = DarwinScopedStorageXFile( DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart index 1706ee616334..e71b59d55115 100644 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart @@ -27,8 +27,7 @@ import 'package:mockito/src/dummies.dart' as _i3; /// A class which mocks [CrossFileDarwinApi]. /// /// See the documentation for Mockito's code generation for more information. -class MockCrossFileDarwinApi extends _i1.Mock - implements _i2.CrossFileDarwinApi { +class MockCrossFileDarwinApi extends _i1.Mock implements _i2.CrossFileDarwinApi { MockCrossFileDarwinApi() { _i1.throwOnMissingStub(this); } From 6ac49c53cd2ef8074108022d6741aa3ee17e6bb5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 11:15:35 -0400 Subject: [PATCH 298/398] return true actually --- ...urceManagerBytesListener.swift => AssetResourceReader.swift} | 2 ++ 1 file changed, 2 insertions(+) rename packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/{AssetResourceManagerBytesListener.swift => AssetResourceReader.swift} (97%) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift similarity index 97% rename from packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift rename to packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift index d290eed7b315..802938653313 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceManagerBytesListener.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift @@ -26,6 +26,8 @@ class AssetResourceReader { self.delegate?.onCompletion(reader: self, error: error?.localizedDescription) } } + + return true } } From 2c0293dc299ae590a1731802152c756674ce3711 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:51:36 -0400 Subject: [PATCH 299/398] docs and names --- .../AssetResourceReader.swift | 19 +- .../CrossFileDarwinApis.g.swift | 226 +++++++---------- .../AssetResourceReaderAPIDelegate.swift | 4 +- .../lib/src/cross_file_darwin_apis.g.dart | 237 +++++++++++------- .../src/darwin_scoped_storage_cross_file.dart | 13 +- .../pigeons/cross_file_darwin_apis.dart | 24 +- 6 files changed, 283 insertions(+), 240 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift index 802938653313..601a26840c5a 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift @@ -4,10 +4,12 @@ import Photos +/// Class for handling an instance of asynchronously reading bytes from +/// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). class AssetResourceReader { var delegate: AssetResourceReaderDelegate? - func openRead(localIdentifier: String) -> Bool { + func startRead(localIdentifier: String) -> Bool { let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) if let asset = assets.firstObject { let resources = PHAssetResource.assetResources(for: asset) @@ -36,6 +38,21 @@ class AssetResourceReader { } protocol AssetResourceReaderDelegate { + /// Provides the requested data. + /// + /// Called multiple times until all bytes are received. + /// + /// Corresponds to the `dataReceivedHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. func onDataReceived(reader: AssetResourceReader, bytes: Data) + + + /// Start reading bytes from the asset with the given identifier. + /// + /// Returns false if the resource for the identifier could not be accessed or + /// found. Returns true if the resource can be successfully accessed. + /// + /// Bytes are passed to `onDataReceived` and the request is completed when + /// `onCompletion` is called. func onCompletion(reader: AssetResourceReader, error: String?) } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index f147905c994e..4cddbba96b33 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -59,9 +59,7 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError( - code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", - details: "") + return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -79,6 +77,7 @@ protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { func onDeinit(identifier: Int64) } + // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -94,18 +93,14 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, - delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( - identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = - objc_getAssociatedObject(instance, associatedObjectKey) - as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -117,6 +112,7 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } + /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -220,8 +216,7 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach( - to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -302,6 +297,7 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } + private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -314,15 +310,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, - instanceManager: CrossFileDarwinApisPigeonInstanceManager? - ) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", - binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -337,9 +327,7 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", - binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -355,13 +343,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference( - identifier identifierArg: Int64, completion: @escaping (Result) -> Void - ) { - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -381,8 +365,7 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiAssetResourceReader] used to add a new Dart instance of /// `AssetResourceReader` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) - -> PigeonApiAssetResourceReader + func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceReader } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -395,15 +378,12 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: - CrossFileDarwinApisPigeonInternalFinalizerDelegate - { + private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -417,9 +397,7 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init( - binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - ) { + init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -428,25 +406,18 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiAssetResourceReader.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: - FlutterStandardReaderWriter -{ +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: - CrossFileDarwinApisPigeonCodecReader - { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -470,9 +441,7 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: - CrossFileDarwinApisPigeonCodecWriter - { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -481,26 +450,24 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] - || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String - { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { super.writeValue(value) return } + if let instance = value as? AssetResourceReader { pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReader(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) return } - if let instance = value as AnyObject?, - pigeonRegistrar.instanceManager.containsInstance(instance) + + if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -518,13 +485,11 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( - data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( - data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) } } @@ -545,58 +510,60 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec( - readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } protocol PigeonApiDelegateAssetResourceReader { - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws - -> AssetResourceReader - func openRead( - pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, - localIdentifier: String - ) throws -> Bool + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws -> AssetResourceReader + /// Start reading bytes from the asset with the given identifier. + /// + /// Returns false if the resource for the identifier could not be accessed or + /// found. Returns true if the resource can be successfully accessed. + /// + /// Bytes are passed to `onDataReceived` and the request is completed when + /// `onCompletion` is called. + func startRead(pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, localIdentifier: String) throws -> Bool } protocol PigeonApiProtocolAssetResourceReader { - func onDataReceived( - pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, - completion: @escaping (Result) -> Void) - func onCompletion( - pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, - completion: @escaping (Result) -> Void) + /// Provides the requested data. + /// + /// Called multiple times until all bytes are received. + /// + /// Corresponds to the `dataReceivedHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. + func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) + /// Indicates the request for data has completed. + /// + /// Called once after the request has been fulfilled or has failed. + /// + /// Corresponds to the `completionHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. + func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, completion: @escaping (Result) -> Void) } -final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { +final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateAssetResourceReader - init( - pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, - delegate: PigeonApiDelegateAssetResourceReader - ) { + init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateAssetResourceReader) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader? - ) { + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader?) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", - binaryMessenger: binaryMessenger, codec: codec) + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", binaryMessenger: binaryMessenger, codec: codec) if let api = api { pigeonDefaultConstructorChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), - withIdentifier: pigeonIdentifierArg) +try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), +withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -605,53 +572,49 @@ final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { } else { pigeonDefaultConstructorChannel.setMessageHandler(nil) } - let openReadChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead", - binaryMessenger: binaryMessenger, codec: codec) + let startReadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead", binaryMessenger: binaryMessenger, codec: codec) if let api = api { - openReadChannel.setMessageHandler { message, reply in + startReadChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! AssetResourceReader let localIdentifierArg = args[1] as! String do { - let result = try api.pigeonDelegate.openRead( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) + let result = try api.pigeonDelegate.startRead(pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) } } } else { - openReadChannel.setMessageHandler(nil) + startReadChannel.setMessageHandler(nil) } } ///Creates a Dart instance of AssetResourceReader and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void - ) { + func pigeonNewInstance(pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { + } else { completion( .failure( PigeonError( code: "new-instance-error", - message: - "Error: Attempting to create a new Dart instance of AssetResourceReader, but the class has a nonnull callback method.", - details: ""))) + message: "Error: Attempting to create a new Dart instance of AssetResourceReader, but the class has a nonnull callback method.", details: ""))) } } - func onDataReceived( - pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, - completion: @escaping (Result) -> Void - ) { + /// Provides the requested data. + /// + /// Called multiple times until all bytes are received. + /// + /// Corresponds to the `dataReceivedHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. + func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -659,22 +622,18 @@ final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: - "Callback to `AssetResourceReader.onDataReceived` failed because native instance was not in the instance manager.", - details: ""))) + message: "Callback to `AssetResourceReader.onDataReceived` failed because native instance was not in the instance manager.", details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, bytesArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -691,10 +650,13 @@ final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { } } - func onCompletion( - pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, - completion: @escaping (Result) -> Void - ) { + /// Indicates the request for data has completed. + /// + /// Called once after the request has been fulfilled or has failed. + /// + /// Corresponds to the `completionHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. + func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, completion: @escaping (Result) -> Void) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -702,22 +664,18 @@ final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: - "Callback to `AssetResourceReader.onCompletion` failed because native instance was not in the instance manager.", - details: ""))) + message: "Callback to `AssetResourceReader.onCompletion` failed because native instance was not in the instance manager.", details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion" + let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, errorArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift index 5f746ee3b9e3..7b49a94e19a9 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift @@ -54,10 +54,10 @@ class AssetResourceReaderAPIDelegate: PigeonApiDelegateAssetResourceReader { return reader } - func openRead( + func startRead( pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, localIdentifier: String ) throws -> Bool { - return pigeonInstance.openRead(localIdentifier: localIdentifier) + return pigeonInstance.startRead(localIdentifier: localIdentifier) } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index f17fe10612c0..58477b821bd1 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -15,9 +15,9 @@ import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, + List? replyList, + String channelName, { + required bool isNullValid, }) { if (replyList == null) { throw PlatformException( @@ -39,6 +39,7 @@ Object? _extractReplyValueOrThrow( return replyList.firstOrNull; } + List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; @@ -48,7 +49,6 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } - /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -60,10 +60,15 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [AssetResourceReader.new]. static AssetResourceReader Function({ - required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, - required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, - })? - assetResourceReader_new; + required void Function( + AssetResourceReader pigeon_instance, + Uint8List bytes, + ) onDataReceived, + required void Function( + AssetResourceReader pigeon_instance, + String? error, + ) onCompletion, + })? assetResourceReader_new; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { @@ -82,7 +87,8 @@ abstract class PigeonInternalProxyApiBaseClass { PigeonInternalProxyApiBaseClass({ this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = pigeon_instanceManager ?? PigeonInstanceManager.instance; + }) : pigeon_instanceManager = + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -154,8 +160,7 @@ class PigeonInstanceManager { final Expando _identifiers = Expando(); final Map> _weakInstances = >{}; - final Map _strongInstances = - {}; + final Map _strongInstances = {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -194,7 +199,8 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference(instance); + _weakInstances[identifier] = + WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -296,7 +302,8 @@ class PigeonInstanceManager { /// Whether this manager contains the given [identifier]. bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || _strongInstances.containsKey(identifier); + return _weakInstances.containsKey(identifier) || + _strongInstances.containsKey(identifier); } int _nextUniqueIdentifier() { @@ -313,7 +320,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -326,10 +333,9 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { @@ -337,14 +343,14 @@ class _PigeonInternalInstanceManagerApi { final List args = message! as List; final int arg_identifier = args[0]! as int; try { - (instanceManager ?? PigeonInstanceManager.instance).remove(arg_identifier); + (instanceManager ?? PigeonInstanceManager.instance) + .remove(arg_identifier); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -359,10 +365,15 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } /// Clear the native `PigeonInstanceManager`. @@ -379,34 +390,40 @@ class _PigeonInternalInstanceManagerApi { final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); } } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager + .getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } } + + class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @override @@ -427,14 +444,20 @@ class _PigeonCodec extends StandardMessageCodec { } } } - -/// Api for getting access to file information. +/// Class for handling an instance of asynchronously reading bytes from +/// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). class AssetResourceReader extends PigeonInternalProxyApiBaseClass { factory AssetResourceReader({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, - required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, + required void Function( + AssetResourceReader pigeon_instance, + Uint8List bytes, + ) onDataReceived, + required void Function( + AssetResourceReader pigeon_instance, + String? error, + ) onCompletion, }) { if (PigeonOverrides.assetResourceReader_new != null) { return PigeonOverrides.assetResourceReader_new!( @@ -457,8 +480,10 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { required this.onDataReceived, required this.onCompletion, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor'; @@ -467,13 +492,16 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([ - pigeonVar_instanceIdentifier, - ]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([pigeonVar_instanceIdentifier]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); + _extractReplyValueOrThrow( + pigeonVar_replyList, + pigeonVar_channelName, + isNullValid: true, + ); }(); } @@ -489,10 +517,16 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { required this.onCompletion, }); - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceReader = + late final _PigeonInternalProxyApiBaseCodec + _pigeonVar_codecAssetResourceReader = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - /// Callback method. + /// Provides the requested data. + /// + /// Called multiple times until all bytes are received. + /// + /// Corresponds to the `dataReceivedHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. /// /// For the associated Native object to be automatically garbage collected, /// it is required that the implementation of this `Function` doesn't have a @@ -511,9 +545,17 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived; + final void Function( + AssetResourceReader pigeon_instance, + Uint8List bytes, + ) onDataReceived; - /// Callback method. + /// Indicates the request for data has completed. + /// + /// Called once after the request has been fulfilled or has failed. + /// + /// Corresponds to the `completionHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. /// /// For the associated Native object to be automatically garbage collected, /// it is required that the implementation of this `Function` doesn't have a @@ -532,44 +574,50 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function(AssetResourceReader pigeon_instance, String? error) onCompletion; + final void Function( + AssetResourceReader pigeon_instance, + String? error, + ) onCompletion; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - void Function(AssetResourceReader pigeon_instance, Uint8List bytes)? onDataReceived, - void Function(AssetResourceReader pigeon_instance, String? error)? onCompletion, + void Function( + AssetResourceReader pigeon_instance, + Uint8List bytes, + )? onDataReceived, + void Function( + AssetResourceReader pigeon_instance, + String? error, + )? onCompletion, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; - final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; + final AssetResourceReader arg_pigeon_instance = + args[0]! as AssetResourceReader; final Uint8List arg_bytes = args[1]! as Uint8List; try { - (onDataReceived ?? arg_pigeon_instance.onDataReceived).call( - arg_pigeon_instance, - arg_bytes, - ); + (onDataReceived ?? arg_pigeon_instance.onDataReceived) + .call(arg_pigeon_instance, arg_bytes); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } @@ -577,46 +625,52 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; - final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; + final AssetResourceReader arg_pigeon_instance = + args[0]! as AssetResourceReader; final String? arg_error = args[1] as String?; try { - (onCompletion ?? arg_pigeon_instance.onCompletion).call(arg_pigeon_instance, arg_error); + (onCompletion ?? arg_pigeon_instance.onCompletion) + .call(arg_pigeon_instance, arg_error); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); + error: PlatformException(code: 'error', message: e.toString())); } }); } } } - Future openRead(String localIdentifier) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; + /// Start reading bytes from the asset with the given identifier. + /// + /// Returns false if the resource for the identifier could not be accessed or + /// found. Returns true if the resource can be successfully accessed. + /// + /// Bytes are passed to `onDataReceived` and the request is completed when + /// `onCompletion` is called. + Future startRead(String localIdentifier) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead'; + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([ - this, - localIdentifier, - ]); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, localIdentifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( @@ -637,3 +691,4 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { ); } } + diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index c23c42f333bd..d186a617856c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -207,7 +207,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final streamController = StreamController(); var currentByteIndex = 0; - final bytesListener = AssetResourceReader( + final reader = AssetResourceReader( onDataReceived: (_, Uint8List bytes) { final int newByteIndex = currentByteIndex + bytes.length; final int startOrZero = start ?? 0; @@ -224,9 +224,6 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final int bytesLeftToRead = end - max(currentByteIndex, startOrZero); if (bytesLeftToRead > 0) { - // late final int bytesStart; - // late final int bytesEnd; - if (currentByteIndex >= startOrZero) { streamController.add(bytes.sublist(0, min(bytesLeftToRead, bytes.length))); } else if (newByteIndex > startOrZero) { @@ -251,7 +248,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile }, ); - bytesListener.openRead(params.uri).then((bool canRead) { + reader.startRead(params.uri).then((bool canRead) { if (!canRead) { streamController.addError( Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), @@ -351,11 +348,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final Pointer uint8Pointer = data.bytes.cast(); final Uint8List byteView = uint8Pointer.asTypedList(data.length); - final a = Uint8List.fromList(byteView); - print('extract: ${a[0]} ${a[1]} ${a[2]} ${a[3]} ${a[4]}'); - print('extract: ${a[a.length - 1]}'); - print('extract: ${a[a.length - 2]}'); - return a; + return Uint8List.fromList(byteView); } } diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart index ff115172d561..316c4db6ed2c 100644 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart @@ -13,14 +13,34 @@ import 'package:pigeon/pigeon.dart'; copyrightHeader: 'pigeons/copyright.txt', ), ) -/// Api for getting access to file information. +/// Class for handling an instance of asynchronously reading bytes from +/// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). @ProxyApi() abstract class AssetResourceReader { AssetResourceReader(); + /// Provides the requested data. + /// + /// Called multiple times until all bytes are received. + /// + /// Corresponds to the `dataReceivedHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. late final void Function(Uint8List bytes) onDataReceived; + /// Indicates the request for data has completed. + /// + /// Called once after the request has been fulfilled or has failed. + /// + /// Corresponds to the `completionHandler` parameter for + /// `PHAssetResourceManager.requestDataForAssetResource`. late final void Function(String? error) onCompletion; - bool openRead(String localIdentifier); + /// Start reading bytes from the asset with the given identifier. + /// + /// Returns false if the resource for the identifier could not be accessed or + /// found. Returns true if the resource can be successfully accessed. + /// + /// Bytes are passed to `onDataReceived` and the request is completed when + /// `onCompletion` is called. + bool startRead(String localIdentifier); } From 712bcf358659247bf1b6aef5b423e9a8650bcdbe Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:53:56 -0400 Subject: [PATCH 300/398] todo --- .../lib/src/darwin_scoped_storage_cross_file.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index d186a617856c..07aa232c6e7c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -198,6 +198,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile return null; } + // TODO(bparrishMines): Implementation should be switched to use `ffigen`. + // Blocked by https://github.com/dart-lang/native/issues/3416. @override Stream openRead([int? start, int? end]) { assert(start == null || start >= 0); From b72833a09e8694627ff344edf15a922e664c0792 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 15:06:51 -0400 Subject: [PATCH 301/398] start initial test creation --- ...n_scoped_storage_cross_directory_test.dart | 86 ------------- ...ed_storage_cross_directory_test.mocks.dart | 70 ---------- ...darwin_scoped_storage_cross_file_test.dart | 121 ------------------ ..._scoped_storage_cross_file_test.mocks.dart | 70 ---------- ...darwin_scoped_storage_cross_file_test.dart | 25 ++++ ..._scoped_storage_cross_file_test.mocks.dart | 98 ++++++++++++++ .../cross_file_darwin/test/test_file.txt | 1 - 7 files changed, 123 insertions(+), 348 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart create mode 100644 packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/test_file.txt diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart deleted file mode 100644 index 62711caf6e48..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:cross_file_darwin/cross_file_darwin.dart'; -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; -import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_directory.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; -import 'package:path/path.dart' as path; - -import 'darwin_scoped_storage_cross_directory_test.mocks.dart'; - -final Directory testDirectory = Directory(path.join(Directory.current.path, 'test')); - -@GenerateMocks([CrossFileDarwinApi]) -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - CrossFilePlatform.instance = CrossFileDarwin(); - }); - - test('exists', () async { - final directory = PlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.uri.toString()), - ); - - expect(await directory.exists(), testDirectory.existsSync()); - }); - - test('list', () async { - final directory = PlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.uri.toString()), - ); - - expect( - (await directory.list(ListParams()).toList()).map( - (PlatformXEntity entity) => entity.params.uri, - ), - (await testDirectory.list().toList()).map((FileSystemEntity entity) => entity.uri.toString()), - ); - }); - - test('canRead', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const result = true; - when(mockApi.isReadableFile(uri)).thenAnswer((_) async => result); - - final directory = DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), - ); - - expect(await directory.canRead(), result); - }); - - test('startAccessingSecurityScopedResource', () async { - final mockApi = MockCrossFileDarwinApi(); - final uri = testDirectory.uri.toString(); - const result = true; - when(mockApi.startAccessingSecurityScopedResource(uri)).thenAnswer((_) async => result); - - final directory = DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), - ); - - expect(await directory.startAccessingSecurityScopedResource(), result); - }); - - test('stopAccessingSecurityScopedResource', () async { - final mockApi = MockCrossFileDarwinApi(); - final uri = testDirectory.uri.toString(); - - final directory = DarwinScopedStorageXDirectory( - DarwinScopedStorageXDirectoryCreationParams(uri: uri, api: mockApi), - ); - - await directory.stopAccessingSecurityScopedResource(); - verify(mockApi.stopAccessingSecurityScopedResource(uri)); - }); -} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart deleted file mode 100644 index ce5b2b295db8..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.mocks.dart +++ /dev/null @@ -1,70 +0,0 @@ -// Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_darwin/test/darwin_scoped_storage_cross_directory_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; -import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i3; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class -// ignore_for_file: invalid_use_of_internal_member - -/// A class which mocks [CrossFileDarwinApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockCrossFileDarwinApi extends _i1.Mock implements _i2.CrossFileDarwinApi { - MockCrossFileDarwinApi() { - _i1.throwOnMissingStub(this); - } - - @override - String get pigeonVar_messageChannelSuffix => - (super.noSuchMethod( - Invocation.getter(#pigeonVar_messageChannelSuffix), - returnValue: _i3.dummyValue( - this, - Invocation.getter(#pigeonVar_messageChannelSuffix), - ), - ) - as String); - - @override - _i4.Future startAccessingSecurityScopedResource(String? url) => - (super.noSuchMethod( - Invocation.method(#startAccessingSecurityScopedResource, [url]), - returnValue: _i4.Future.value(false), - ) - as _i4.Future); - - @override - _i4.Future stopAccessingSecurityScopedResource(String? url) => - (super.noSuchMethod( - Invocation.method(#stopAccessingSecurityScopedResource, [url]), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) - as _i4.Future); - - @override - _i4.Future isReadableFile(String? url) => - (super.noSuchMethod( - Invocation.method(#isReadableFile, [url]), - returnValue: _i4.Future.value(false), - ) - as _i4.Future); -} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart deleted file mode 100644 index bd2aa1630307..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:cross_file_darwin/cross_file_darwin.dart'; -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; -import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; -import 'package:path/path.dart' as path; - -import 'darwin_scoped_storage_cross_file_test.mocks.dart'; - -final File testFile = File(path.join(Directory.current.path, 'test', 'test_file.txt')); - -@GenerateMocks([CrossFileDarwinApi]) -void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - - setUp(() { - CrossFilePlatform.instance = CrossFileDarwin(); - }); - - test('lastModified', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.lastModified(), testFile.lastModifiedSync()); - }); - - test('length', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.length(), await testFile.length()); - }); - - test('openRead', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.openRead().toList(), await testFile.openRead().toList()); - }); - - test('readAsBytes', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.readAsBytes(), await testFile.readAsBytes()); - }); - - test('readAsString', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.readAsString(), await testFile.readAsString()); - }); - - test('canRead', () async { - final mockApi = MockCrossFileDarwinApi(); - const uri = 'uri'; - const result = true; - when(mockApi.isReadableFile(uri)).thenAnswer((_) async => result); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.canRead(), result); - }); - - test('exists', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.exists(), testFile.existsSync()); - }); - - test('name', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect(await file.name(), 'test_file.txt'); - }); - - test('startAccessingSecurityScopedResource', () async { - final mockApi = MockCrossFileDarwinApi(); - final uri = testFile.uri.toString(); - const result = true; - when(mockApi.startAccessingSecurityScopedResource(uri)).thenAnswer((_) async => result); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - expect(await file.startAccessingSecurityScopedResource(), result); - }); - - test('stopAccessingSecurityScopedResource', () async { - final mockApi = MockCrossFileDarwinApi(); - final uri = testFile.uri.toString(); - - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams(uri: uri, api: mockApi), - ); - - await file.stopAccessingSecurityScopedResource(); - verify(mockApi.stopAccessingSecurityScopedResource(uri)); - }); -} diff --git a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart deleted file mode 100644 index e71b59d55115..000000000000 --- a/packages/cross_file/cross_file_darwin/test/darwin_scoped_storage_cross_file_test.mocks.dart +++ /dev/null @@ -1,70 +0,0 @@ -// Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_darwin/test/darwin_scoped_storage_cross_file_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; -import 'package:mockito/mockito.dart' as _i1; -import 'package:mockito/src/dummies.dart' as _i3; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class -// ignore_for_file: invalid_use_of_internal_member - -/// A class which mocks [CrossFileDarwinApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockCrossFileDarwinApi extends _i1.Mock implements _i2.CrossFileDarwinApi { - MockCrossFileDarwinApi() { - _i1.throwOnMissingStub(this); - } - - @override - String get pigeonVar_messageChannelSuffix => - (super.noSuchMethod( - Invocation.getter(#pigeonVar_messageChannelSuffix), - returnValue: _i3.dummyValue( - this, - Invocation.getter(#pigeonVar_messageChannelSuffix), - ), - ) - as String); - - @override - _i4.Future startAccessingSecurityScopedResource(String? url) => - (super.noSuchMethod( - Invocation.method(#startAccessingSecurityScopedResource, [url]), - returnValue: _i4.Future.value(false), - ) - as _i4.Future); - - @override - _i4.Future stopAccessingSecurityScopedResource(String? url) => - (super.noSuchMethod( - Invocation.method(#stopAccessingSecurityScopedResource, [url]), - returnValue: _i4.Future.value(), - returnValueForMissingStub: _i4.Future.value(), - ) - as _i4.Future); - - @override - _i4.Future isReadableFile(String? url) => - (super.noSuchMethod( - Invocation.method(#isReadableFile, [url]), - returnValue: _i4.Future.value(false), - ) - as _i4.Future); -} diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart new file mode 100644 index 000000000000..1051e9b5e3b2 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -0,0 +1,25 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_darwin/cross_file_darwin.dart'; +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; +import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'package:path/path.dart' as path; + +import 'photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart'; + +@GenerateMocks([AssetResourceReader]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + setUp(() { + CrossFilePlatform.instance = CrossFileDarwin(); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart new file mode 100644 index 000000000000..f2b37b39bf0f --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart @@ -0,0 +1,98 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i4; +import 'dart:typed_data' as _i3; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeAssetResourceReader_1 extends _i1.SmartFake + implements _i2.AssetResourceReader { + _FakeAssetResourceReader_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [AssetResourceReader]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockAssetResourceReader extends _i1.Mock + implements _i2.AssetResourceReader { + MockAssetResourceReader() { + _i1.throwOnMissingStub(this); + } + + @override + void Function(_i2.AssetResourceReader, _i3.Uint8List) get onDataReceived => + (super.noSuchMethod( + Invocation.getter(#onDataReceived), + returnValue: + ( + _i2.AssetResourceReader pigeon_instance, + _i3.Uint8List bytes, + ) {}, + ) + as void Function(_i2.AssetResourceReader, _i3.Uint8List)); + + @override + void Function(_i2.AssetResourceReader, String?) get onCompletion => + (super.noSuchMethod( + Invocation.getter(#onCompletion), + returnValue: + (_i2.AssetResourceReader pigeon_instance, String? error) {}, + ) + as void Function(_i2.AssetResourceReader, String?)); + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i4.Future startRead(String? localIdentifier) => + (super.noSuchMethod( + Invocation.method(#startRead, [localIdentifier]), + returnValue: _i4.Future.value(false), + ) + as _i4.Future); + + @override + _i2.AssetResourceReader pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeAssetResourceReader_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.AssetResourceReader); +} diff --git a/packages/cross_file/cross_file_darwin/test/test_file.txt b/packages/cross_file/cross_file_darwin/test/test_file.txt deleted file mode 100644 index b45ef6fec895..000000000000 --- a/packages/cross_file/cross_file_darwin/test/test_file.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, World! \ No newline at end of file From f99d7ed12a161de01a45b62647ccac26114f6df9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 15:28:57 -0400 Subject: [PATCH 302/398] start writing tests --- ...darwin_scoped_storage_cross_file_test.dart | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart index 1051e9b5e3b2..328e00ef5159 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -2,24 +2,58 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:io'; +import 'dart:typed_data'; -import 'package:cross_file_darwin/cross_file_darwin.dart'; import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; -import 'package:path/path.dart' as path; import 'photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart'; @GenerateMocks([AssetResourceReader]) void main() { - TestWidgetsFlutterBinding.ensureInitialized(); - setUp(() { - CrossFilePlatform.instance = CrossFileDarwin(); + PigeonOverrides.pigeon_reset(); + }); + + test('PhotoKitDarwinScopedStorageXFile.openRead', () async { + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), + ); + + final MockAssetResourceReader reader = setUpReader(); + + final Stream stream = file.openRead(); + + final bytes = Uint8List.fromList([1, 2, 3]); + reader.onDataReceived(reader, bytes); + + expect( + await stream.reduce( + (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), + ), + bytes, + ); + }); +} + +MockAssetResourceReader setUpReader() { + final reader = MockAssetResourceReader(); + when(reader.startRead('id')).thenAnswer((_) async { + return true; }); + + PigeonOverrides.assetResourceReader_new = + ({ + required void Function(AssetResourceReader instance, Uint8List bytes) onDataReceived, + required void Function(AssetResourceReader instance, String? error) onCompletion, + }) { + when(reader.onDataReceived).thenReturn(onDataReceived); + when(reader.onCompletion).thenReturn(onCompletion); + return reader; + }; + + return reader; } From b57339ce6b0f443cd090e3e1b33648eb57c2a9e2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 15:33:43 -0400 Subject: [PATCH 303/398] passing test --- .../src/darwin_scoped_storage_cross_file.dart | 90 +++++++++---------- ...darwin_scoped_storage_cross_file_test.dart | 1 + 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 07aa232c6e7c..0cc24efe549c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -205,63 +205,59 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile assert(start == null || start >= 0); assert(end == null || end >= (start ?? 0)); - if (_tryGetAssetResource(identifier: params.uri) != null) { - final streamController = StreamController(); - var currentByteIndex = 0; + final streamController = StreamController(); + var currentByteIndex = 0; - final reader = AssetResourceReader( - onDataReceived: (_, Uint8List bytes) { - final int newByteIndex = currentByteIndex + bytes.length; - final int startOrZero = start ?? 0; + final reader = AssetResourceReader( + onDataReceived: (_, Uint8List bytes) { + final int newByteIndex = currentByteIndex + bytes.length; + final int startOrZero = start ?? 0; - if (end == null) { - if (currentByteIndex >= startOrZero) { - streamController.add(bytes); - } else { - if (newByteIndex > startOrZero) { - streamController.add(bytes.sublist(startOrZero - currentByteIndex)); - } - } + if (end == null) { + if (currentByteIndex >= startOrZero) { + streamController.add(bytes); } else { - final int bytesLeftToRead = end - max(currentByteIndex, startOrZero); - - if (bytesLeftToRead > 0) { - if (currentByteIndex >= startOrZero) { - streamController.add(bytes.sublist(0, min(bytesLeftToRead, bytes.length))); - } else if (newByteIndex > startOrZero) { - streamController.add( - bytes.sublist( - startOrZero - currentByteIndex, - min(startOrZero - currentByteIndex + bytesLeftToRead, bytes.length), - ), - ); - } + if (newByteIndex > startOrZero) { + streamController.add(bytes.sublist(startOrZero - currentByteIndex)); } } + } else { + final int bytesLeftToRead = end - max(currentByteIndex, startOrZero); - currentByteIndex = newByteIndex; - }, - onCompletion: (_, String? error) { - if (error != null) { - streamController.addError(Exception(error)); + if (bytesLeftToRead > 0) { + if (currentByteIndex >= startOrZero) { + streamController.add(bytes.sublist(0, min(bytesLeftToRead, bytes.length))); + } else if (newByteIndex > startOrZero) { + streamController.add( + bytes.sublist( + startOrZero - currentByteIndex, + min(startOrZero - currentByteIndex + bytesLeftToRead, bytes.length), + ), + ); + } } + } - streamController.close(); - }, - ); - - reader.startRead(params.uri).then((bool canRead) { - if (!canRead) { - streamController.addError( - Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), - ); - streamController.close(); + currentByteIndex = newByteIndex; + }, + onCompletion: (_, String? error) { + if (error != null) { + streamController.addError(Exception(error)); } - }); - return streamController.stream; - } - throw Exception('Failed to retrieve PHAssetResource for asset with identifier: ${params.uri}'); + streamController.close(); + }, + ); + + reader.startRead(params.uri).then((bool canRead) { + if (!canRead) { + streamController.addError( + Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), + ); + streamController.close(); + } + }); + return streamController.stream; } @override diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart index 328e00ef5159..dda527b416e6 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -29,6 +29,7 @@ void main() { final bytes = Uint8List.fromList([1, 2, 3]); reader.onDataReceived(reader, bytes); + reader.onCompletion(reader, null); expect( await stream.reduce( From f52b220b3118a1b8a59c13d328fca78a4752d230 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 15 Jun 2026 17:31:25 -0400 Subject: [PATCH 304/398] initial stress test --- ...darwin_scoped_storage_cross_file_test.dart | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart index dda527b416e6..39673a63eda4 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -18,25 +18,52 @@ void main() { PigeonOverrides.pigeon_reset(); }); - test('PhotoKitDarwinScopedStorageXFile.openRead', () async { - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), - ); + group('openRead', () { + test('null start and null end', () async { + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), + ); - final MockAssetResourceReader reader = setUpReader(); + final MockAssetResourceReader reader = setUpReader(); - final Stream stream = file.openRead(); + final Stream stream = file.openRead(); - final bytes = Uint8List.fromList([1, 2, 3]); - reader.onDataReceived(reader, bytes); - reader.onCompletion(reader, null); + final bytes = Uint8List.fromList([1, 2, 3]); + reader.onDataReceived(reader, bytes); + reader.onCompletion(reader, null); - expect( - await stream.reduce( - (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), - ), - bytes, - ); + expect( + await stream.reduce( + (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), + ), + bytes, + ); + }); + + test('oijspio', () async { + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), + ); + + final MockAssetResourceReader reader = setUpReader(); + + final Stream stream = file.openRead(2, 8); + + final allBytes = Uint8List.fromList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); + reader.onDataReceived(reader, allBytes.sublist(0, 2)); + reader.onDataReceived(reader, allBytes.sublist(2, 4)); + reader.onDataReceived(reader, allBytes.sublist(4, 6)); + reader.onDataReceived(reader, allBytes.sublist(6, 8)); + reader.onDataReceived(reader, allBytes.sublist(8, 10)); + reader.onCompletion(reader, null); + + expect( + await stream.reduce( + (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), + ), + allBytes.sublist(2, 8), + ); + }); }); } From ae5434c7006d611930c5012e70c864417412354a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:53:48 -0400 Subject: [PATCH 305/398] add tests back --- ...darwin_scoped_storage_cross_file_test.dart | 27 ++++--- ...n_scoped_storage_cross_directory_test.dart | 39 ++++++++++ ...darwin_scoped_storage_cross_file_test.dart | 74 +++++++++++++++++++ .../cross_file_darwin/test/test_file.txt | 1 + 4 files changed, 130 insertions(+), 11 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/test_file.txt diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart index 39673a63eda4..a93ccf67b690 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -19,7 +19,7 @@ void main() { }); group('openRead', () { - test('null start and null end', () async { + test('correctly reads all bytes with null start and null end', () async { final file = DarwinScopedStorageXFile( DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), ); @@ -40,28 +40,33 @@ void main() { ); }); - test('oijspio', () async { + test('correctly reads desired sublist', () async { final file = DarwinScopedStorageXFile( DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), ); final MockAssetResourceReader reader = setUpReader(); - final Stream stream = file.openRead(2, 8); - - final allBytes = Uint8List.fromList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); - reader.onDataReceived(reader, allBytes.sublist(0, 2)); - reader.onDataReceived(reader, allBytes.sublist(2, 4)); - reader.onDataReceived(reader, allBytes.sublist(4, 6)); - reader.onDataReceived(reader, allBytes.sublist(6, 8)); - reader.onDataReceived(reader, allBytes.sublist(8, 10)); + final bytes = Uint8List.fromList([0, 1, 2, 3, 4]); + final Stream stream = file.openRead(1, 4); + + // Ignore byte before desired sublist. + reader.onDataReceived(reader, Uint8List.fromList([bytes[0]])); + // Read byte at start of desired sublist. + reader.onDataReceived(reader, Uint8List.fromList([bytes[1]])); + // Read byte between start and end of desired sublist. + reader.onDataReceived(reader, Uint8List.fromList([bytes[2]])); + // Read byte at end of desire sublist + reader.onDataReceived(reader, Uint8List.fromList([bytes[3]])); + // Ignore byte after desired sublist. + reader.onDataReceived(reader, Uint8List.fromList([bytes[4]])); reader.onCompletion(reader, null); expect( await stream.reduce( (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), ), - allBytes.sublist(2, 8), + bytes.sublist(1, 4), ); }); }); diff --git a/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart new file mode 100644 index 000000000000..1b738b609eab --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_darwin/cross_file_darwin.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; + +final Directory testDirectory = Directory(path.join(Directory.current.path, 'test')); + +void main() { + setUp(() { + CrossFilePlatform.instance = CrossFileDarwin(); + }); + + test('exists', () async { + final directory = PlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.uri.toString()), + ); + + expect(await directory.exists(), testDirectory.existsSync()); + }); + + test('list', () async { + final directory = PlatformScopedStorageXDirectory( + PlatformScopedStorageXDirectoryCreationParams(uri: testDirectory.uri.toString()), + ); + + expect( + (await directory.list(ListParams()).toList()).map( + (PlatformXEntity entity) => entity.params.uri, + ), + (await testDirectory.list().toList()).map((FileSystemEntity entity) => entity.uri.toString()), + ); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_file_test.dart new file mode 100644 index 000000000000..a8585fbd5e4e --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_file_test.dart @@ -0,0 +1,74 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_darwin/cross_file_darwin.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:path/path.dart' as path; + +final File testFile = File(path.join(Directory.current.path, 'test', 'test_file.txt')); + +void main() { + setUp(() { + CrossFilePlatform.instance = CrossFileDarwin(); + }); + + test('lastModified', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.lastModified(), testFile.lastModifiedSync()); + }); + + test('length', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.length(), await testFile.length()); + }); + + test('openRead', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.openRead().toList(), await testFile.openRead().toList()); + }); + + test('readAsBytes', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.readAsBytes(), await testFile.readAsBytes()); + }); + + test('readAsString', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.readAsString(), await testFile.readAsString()); + }); + + test('exists', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.exists(), testFile.existsSync()); + }); + + test('name', () async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFile.uri.toString()), + ); + + expect(await file.name(), 'test_file.txt'); + }); +} diff --git a/packages/cross_file/cross_file_darwin/test/test_file.txt b/packages/cross_file/cross_file_darwin/test/test_file.txt new file mode 100644 index 000000000000..b45ef6fec895 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/test_file.txt @@ -0,0 +1 @@ +Hello, World! \ No newline at end of file From 42e67e6c4097a3f67fee6c27e530d702327ba53e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:32:14 -0400 Subject: [PATCH 306/398] impl tests --- ...s.swift => AssetResourceReaderTests.swift} | 26 ++------- .../darwin/Tests/TestProxyAPIRegistrar.swift | 56 +++++++++++++++++++ .../AssetResourceReader.swift | 5 +- .../ios/Runner.xcodeproj/project.pbxproj | 22 +++++--- .../example/ios/RunnerTests/Info.plist | 22 ++++++++ .../cross_file_darwin/example/pubspec.yaml | 2 +- 6 files changed, 102 insertions(+), 31 deletions(-) rename packages/cross_file/cross_file_darwin/darwin/Tests/{CrossFileDarwinApiTests.swift => AssetResourceReaderTests.swift} (50%) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift create mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift similarity index 50% rename from packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift rename to packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift index c556fcb2e62f..2749671856be 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinApiTests.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift @@ -14,7 +14,7 @@ import Testing #error("Unsupported platform.") #endif -struct CrossFileDarwinApiTests { +struct AssetResourceReaderTests { func createTempTestFile() throws -> URL { let fileManager = FileManager.default let tempDirectory = fileManager.temporaryDirectory @@ -26,25 +26,11 @@ struct CrossFileDarwinApiTests { return fileURL } - @Test func startAccessingSecurityScopedResource() throws { - let testFileURL = try createTempTestFile() + @Test func pigeonDefaultConstructor() throws { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiAssetResourceReader(registrar) - let api = CrossFileDarwinApiImpl() - let canAccess = try api.startAccessingSecurityScopedResource(url: testFileURL.absoluteString) - - // Only returns true on iOS. - #if os(iOS) - #expect(canAccess) - #endif - - #expect(try String(contentsOf: testFileURL, encoding: .utf8) == "Hello, World!") - } - - @Test func isReadableFile() throws { - let testFileURL = try createTempTestFile() - - let api = CrossFileDarwinApiImpl() - - #expect(try api.isReadableFile(url: testFileURL.absoluteString)) + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api) + #expect(instance != nil) } } diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift new file mode 100644 index 000000000000..405bada8def5 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift @@ -0,0 +1,56 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import XCTest + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +@testable import cross_file_darwin + +class TestProxyApiRegistrar: ProxyAPIRegistrar { + init() { + super.init( + binaryMessenger: TestBinaryMessenger()) + } + + override func dispatchOnMainThread( + execute work: @escaping (@escaping (String, PigeonError) -> Void) -> Void + ) { + work { _, _ in } + } +} + +class TestBundle: Bundle, @unchecked Sendable { + override func url(forResource name: String?, withExtension ext: String?) -> URL? { + return URL(string: "assets/www/index.html")! + } +} + +class TestBinaryMessenger: NSObject, FlutterBinaryMessenger { + func send(onChannel channel: String, message: Data?) { + + } + + func send( + onChannel channel: String, message: Data?, binaryReply callback: FlutterBinaryReply? = nil + ) { + + } + + func setMessageHandlerOnChannel( + _ channel: String, binaryMessageHandler handler: FlutterBinaryMessageHandler? = nil + ) -> FlutterBinaryMessengerConnection { + return 0 + } + + func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) { + + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift index 601a26840c5a..b5ed1e6484c5 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift @@ -5,10 +5,12 @@ import Photos /// Class for handling an instance of asynchronously reading bytes from -/// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). +/// `PHAssetResourceManager.requestDataForAssetResource`. class AssetResourceReader { + /// Handles the bytes read. var delegate: AssetResourceReaderDelegate? + /// Begin reading bytes from PHAssetResource with `localIdentifier`. func startRead(localIdentifier: String) -> Bool { let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) if let asset = assets.firstObject { @@ -37,6 +39,7 @@ class AssetResourceReader { } } +/// Handles bytes read from calling `AssetResourceReader.startRead`. protocol AssetResourceReaderDelegate { /// Provides the requested data. /// diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index a6a54c29f2bd..2ecc9bd9d22c 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ @@ -12,7 +12,8 @@ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */; }; + 8F2171F72F21A5270014CE68 /* AssetResourceReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* AssetResourceReaderTests.swift */; }; + 8FF93F5B2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F5A2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -48,10 +49,13 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../darwin/cross_file_darwin; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; + 8F2171F52F21A5270014CE68 /* AssetResourceReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AssetResourceReaderTests.swift; path = ../../darwin/Tests/AssetResourceReaderTests.swift; sourceTree = SOURCE_ROOT; }; + 8FF93F5A2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = ../../darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = SOURCE_ROOT; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -59,8 +63,6 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; - 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../darwin/cross_file_darwin; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -85,7 +87,8 @@ 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 8F2171F52F21A5270014CE68 /* CrossFileDarwinApiTests.swift */, + 8FF93F5A2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift */, + 8F2171F52F21A5270014CE68 /* AssetResourceReaderTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -221,7 +224,7 @@ ); mainGroup = 97C146E51CF9000F007C117D; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; @@ -293,7 +296,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F2171F72F21A5270014CE68 /* CrossFileDarwinApiTests.swift in Sources */, + 8F2171F72F21A5270014CE68 /* AssetResourceReaderTests.swift in Sources */, + 8FF93F5B2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -651,7 +655,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist new file mode 100644 index 000000000000..64d65ca49577 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 4d99fc220b48..6ef0db20ba87 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -7,7 +7,6 @@ environment: flutter: ">=3.38.0" dependencies: - cupertino_icons: ^1.0.8 cross_file_darwin: # When depending on this package from a real application you should use: # cross_file_darwin: ^x.y.z @@ -15,6 +14,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ + cupertino_icons: ^1.0.8 file_selector: git: url: https://github.com/bparrishMines/packages From 55eeb13a5322d59936bcbc0ff183409a6a548b25 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:39:24 -0400 Subject: [PATCH 307/398] add macos tests --- .../macos/Runner.xcodeproj/project.pbxproj | 32 +++++++++++++++---- .../RunnerTests/RunnerTests-Bridging-Header.h | 3 ++ 2 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests-Bridging-Header.h diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index 1b6877440d11..356a47461c89 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXAggregateTarget section */ @@ -27,7 +27,8 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 8FB3B0B92F3D820100A1CEDF /* CrossFileDarwinApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */; }; + 8FF93F5E2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F5D2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift */; }; + 8FF93F5F2FE2F63600F3D52F /* AssetResourceReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F5C2FE2F63600F3D52F /* AssetResourceReaderTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -76,9 +77,13 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../../darwin/cross_file_darwin; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinApiTests.swift; path = ../../darwin/Tests/CrossFileDarwinApiTests.swift; sourceTree = SOURCE_ROOT; }; + 8FF93F5C2FE2F63600F3D52F /* AssetResourceReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AssetResourceReaderTests.swift; path = ../../darwin/Tests/AssetResourceReaderTests.swift; sourceTree = SOURCE_ROOT; }; + 8FF93F5D2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = ../../darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = SOURCE_ROOT; }; + 8FF93F602FE2F63800F3D52F /* RunnerTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RunnerTests-Bridging-Header.h"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -104,7 +109,9 @@ 331C80D6294CF71000263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 8FB3B0B62F3D820100A1CEDF /* CrossFileDarwinApiTests.swift */, + 8FF93F5C2FE2F63600F3D52F /* AssetResourceReaderTests.swift */, + 8FF93F5D2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift */, + 8FF93F602FE2F63800F3D52F /* RunnerTests-Bridging-Header.h */, ); path = RunnerTests; sourceTree = ""; @@ -154,6 +161,8 @@ 33CEB47122A05771004F2AC0 /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* cross_file_darwin */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, @@ -240,6 +249,7 @@ TargetAttributes = { 331C80D4294CF70F00263BE5 = { CreatedOnToolsVersion = 14.0; + LastSwiftMigration = 2640; TestTargetID = 33CC10EC2044A3C60003C045; }; 33CC10EC2044A3C60003C045 = { @@ -268,7 +278,7 @@ ); mainGroup = 33CC10E42044A3C60003C045; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; projectDirPath = ""; @@ -346,7 +356,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8FB3B0B92F3D820100A1CEDF /* CrossFileDarwinApiTests.swift in Sources */, + 8FF93F5E2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift in Sources */, + 8FF93F5F2FE2F63600F3D52F /* AssetResourceReaderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -392,11 +403,14 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_darwin_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_darwin_example"; }; @@ -406,11 +420,13 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_darwin_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_darwin_example"; }; @@ -420,11 +436,13 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.packages.crossFileDarwinExample.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/cross_file_darwin_example.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/cross_file_darwin_example"; }; @@ -712,7 +730,7 @@ /* End XCConfigurationList section */ /* Begin XCLocalSwiftPackageReference section */ - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */ = { isa = XCLocalSwiftPackageReference; relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; }; diff --git a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests-Bridging-Header.h b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests-Bridging-Header.h new file mode 100644 index 000000000000..b8fa2a34b670 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/RunnerTests-Bridging-Header.h @@ -0,0 +1,3 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. From 8e7618067d110fb144e70960bd865a9ca620d7ad Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:53:12 -0400 Subject: [PATCH 308/398] formatting and no import --- .../integration_test/cross_file_test.dart | 4 +- .../cross_file/example/lib/main.dart | 20 +- .../cross_file/lib/src/cross_file.dart | 6 +- .../src/scoped_storage_cross_directory.dart | 17 +- .../lib/src/scoped_storage_cross_file.dart | 17 +- .../cross_file/test/cross_directory_test.dart | 5 +- .../cross_file/test/cross_file_test.dart | 5 +- .../scoped_storage_cross_directory_test.dart | 23 +- .../test/scoped_storage_cross_file_test.dart | 56 +-- .../cross_file/test/test_stubs.dart | 35 +- .../cross_file_android/example/lib/main.dart | 20 +- .../lib/src/android_library.g.dart | 353 ++++++------------ ...ndroid_scoped_storage_cross_directory.dart | 11 +- .../android_scoped_storage_cross_file.dart | 14 +- .../pigeons/android_library.dart | 14 +- ...d_scoped_storage_cross_directory_test.dart | 38 +- ...ed_storage_cross_directory_test.mocks.dart | 25 +- ...ndroid_scoped_storage_cross_file_test.dart | 183 ++++----- ..._scoped_storage_cross_file_test.mocks.dart | 46 +-- .../darwin/Tests/TestProxyAPIRegistrar.swift | 8 +- .../AssetResourceReader.swift | 3 +- .../CrossFileDarwinApis.g.swift | 191 +++++++--- .../cross_file_darwin/example/pubspec.yaml | 7 - .../lib/src/cross_file_darwin_apis.g.dart | 209 +++++------ ..._scoped_storage_cross_file_test.mocks.dart | 23 +- .../cross_file_io/example/lib/main.dart | 20 +- .../cross_file_io/lib/cross_file_io.dart | 6 +- .../cross_file_io/lib/src/cross_file_io.dart | 7 +- .../lib/src/io_cross_directory.dart | 14 +- .../cross_file_io/lib/src/io_cross_file.dart | 16 +- .../test/io_cross_directory_test.dart | 4 +- .../test/io_cross_file_test.dart | 39 +- .../lib/src/cross_file_platform.dart | 7 +- .../lib/src/platform_cross_directory.dart | 10 +- .../lib/src/platform_cross_file.dart | 3 +- ...atform_scoped_storage_cross_directory.dart | 14 +- .../platform_scoped_storage_cross_file.dart | 12 +- .../test/cross_file_platform_test.dart | 12 +- .../cross_file_web/example/lib/main.dart | 20 +- .../lib/src/cross_file_web.dart | 3 +- .../cross_file_web/lib/src/web_helpers.dart | 14 +- .../src/web_scoped_storage_cross_file.dart | 22 +- .../test/web_cross_file_test.dart | 29 +- 43 files changed, 596 insertions(+), 989 deletions(-) diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart index f11767706210..c20b611a38e7 100644 --- a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -15,9 +15,7 @@ import 'package:path_provider/path_provider.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('Can read from file using dart:io implementation', ( - WidgetTester tester, - ) async { + testWidgets('Can read from file using dart:io implementation', (WidgetTester tester) async { final Directory dir = await getApplicationCacheDirectory(); final xDir = XDirectory.fromPath(dir.path); diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index 8098b98b804d..2107c6cbe6f8 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -71,10 +71,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), + appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -105,11 +102,7 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay({ - super.key, - required this.filename, - required this.fileContents, - }); + const TextDisplay({super.key, required this.filename, required this.fileContents}); /// The name of the file. final String filename; @@ -121,14 +114,9 @@ class TextDisplay extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( title: Text(filename), - content: Scrollbar( - child: SingleChildScrollView(child: Text(fileContents)), - ), + content: Scrollbar(child: SingleChildScrollView(child: Text(fileContents))), actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), + TextButton(child: const Text('Close'), onPressed: () => Navigator.pop(context)), ], ); } diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 9df74576d654..84b791c684a9 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -36,8 +36,7 @@ base class XFile extends XEntity { /// /// See [XFile.fromCreationParams] for setting parameters for a specific /// platform. - XFile({required String uri}) - : this.fromCreationParams(PlatformXFileCreationParams(uri: uri)); + XFile({required String uri}) : this.fromCreationParams(PlatformXFileCreationParams(uri: uri)); /// Constructs a [XFile] from a [Uri]. XFile.fromUri(Uri uri) : this(uri: uri.toString()); @@ -109,8 +108,7 @@ base class XFile extends XEntity { /// /// Platforms may throw an exception if there is an error opening or reading /// the resource. - Stream openRead([int? start, int? end]) => - platform.openRead(start, end); + Stream openRead([int? start, int? end]) => platform.openRead(start, end); /// Reads the entire resource contents as a list of bytes. /// diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index 304e338c9565..6d571cd74ef9 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -39,9 +39,7 @@ base class ScopedStorageXDirectory extends XDirectory { /// See [ScopedStorageXDirectory.fromCreationParams] for setting parameters /// for a specific platform. ScopedStorageXDirectory({required String uri}) - : this.fromCreationParams( - PlatformScopedStorageXDirectoryCreationParams(uri: uri), - ); + : this.fromCreationParams(PlatformScopedStorageXDirectoryCreationParams(uri: uri)); /// Constructs a [ScopedStorageXDirectory]. /// @@ -68,21 +66,18 @@ base class ScopedStorageXDirectory extends XDirectory { /// final file = ScopedStorageXDirectory.fromCreationParams(params); /// ``` /// {@endtemplate} - ScopedStorageXDirectory.fromCreationParams( - PlatformScopedStorageXDirectoryCreationParams params, - ) : this.fromPlatform(PlatformScopedStorageXDirectory(params)); + ScopedStorageXDirectory.fromCreationParams(PlatformScopedStorageXDirectoryCreationParams params) + : this.fromPlatform(PlatformScopedStorageXDirectory(params)); /// Constructs a [ScopedStorageXDirectory] from a specific platform /// implementation. @internal - const ScopedStorageXDirectory.fromPlatform( - PlatformScopedStorageXDirectory super.platform, - ) : super.fromPlatform(); + const ScopedStorageXDirectory.fromPlatform(PlatformScopedStorageXDirectory super.platform) + : super.fromPlatform(); @internal @override - PlatformScopedStorageXDirectory get platform => - super.platform as PlatformScopedStorageXDirectory; + PlatformScopedStorageXDirectory get platform => super.platform as PlatformScopedStorageXDirectory; /// Whether the directory represented by this reference can be read. Future canRead() => platform.canRead(); diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index 5dc519b509ac..a873c126d79c 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -38,9 +38,7 @@ base class ScopedStorageXFile extends XFile { /// See [ScopedStorageXFile.fromCreationParams] for setting parameters /// for a specific platform. ScopedStorageXFile({required String uri}) - : this.fromCreationParams( - PlatformScopedStorageXFileCreationParams(uri: uri), - ); + : this.fromCreationParams(PlatformScopedStorageXFileCreationParams(uri: uri)); /// Constructs a [ScopedStorageXFile]. /// @@ -67,20 +65,17 @@ base class ScopedStorageXFile extends XFile { /// final file = ScopedStorageXFile.fromCreationParams(params); /// ``` /// {@endtemplate} - ScopedStorageXFile.fromCreationParams( - PlatformScopedStorageXFileCreationParams params, - ) : this.fromPlatform(PlatformScopedStorageXFile(params)); + ScopedStorageXFile.fromCreationParams(PlatformScopedStorageXFileCreationParams params) + : this.fromPlatform(PlatformScopedStorageXFile(params)); /// Constructs a [ScopedStorageXFile] from a specific platform implementation. @internal - const ScopedStorageXFile.fromPlatform( - PlatformScopedStorageXFile super.platform, - ) : super.fromPlatform(); + const ScopedStorageXFile.fromPlatform(PlatformScopedStorageXFile super.platform) + : super.fromPlatform(); @internal @override - PlatformScopedStorageXFile get platform => - super.platform as PlatformScopedStorageXFile; + PlatformScopedStorageXFile get platform => super.platform as PlatformScopedStorageXFile; /// Whether the resource represented by this reference can be read. Future canRead() => platform.canRead(); diff --git a/packages/cross_file/cross_file/test/cross_directory_test.dart b/packages/cross_file/cross_file/test/cross_directory_test.dart index 9cadc0b16049..e25ec6da5b2d 100644 --- a/packages/cross_file/cross_file/test/cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/cross_directory_test.dart @@ -30,10 +30,7 @@ void main() { ]; CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformXDirectory: (PlatformXDirectoryCreationParams params) => - TestXDirectory( - params, - onList: (ListParams params) => Stream.fromIterable(entities), - ), + TestXDirectory(params, onList: (ListParams params) => Stream.fromIterable(entities)), ); final directory = XDirectory(uri: 'uri'); diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart index a81caa9c4a0d..d92065310bc7 100644 --- a/packages/cross_file/cross_file/test/cross_file_test.dart +++ b/packages/cross_file/cross_file/test/cross_file_test.dart @@ -67,10 +67,7 @@ void main() { const message = 'Hello, World!'; CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile( - params, - onReadAsString: ({required Encoding encoding}) async => message, - ), + TestXFile(params, onReadAsString: ({required Encoding encoding}) async => message), ); final file = XFile(uri: 'uri'); diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 7f8aa4df4640..8b9bab0903c1 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -15,10 +15,7 @@ void main() { CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformScopedStorageXDirectory: (PlatformScopedStorageXDirectoryCreationParams params) => - TestScopedStorageXDirectory( - params, - onExists: () async => exists, - ), + TestScopedStorageXDirectory(params, onExists: () async => exists), ); final directory = ScopedStorageXDirectory(uri: 'uri'); @@ -28,9 +25,7 @@ void main() { test('list', () async { final entities = [ - TestScopedStorageXFile( - const PlatformScopedStorageXFileCreationParams(uri: 'uri1'), - ), + TestScopedStorageXFile(const PlatformScopedStorageXFileCreationParams(uri: 'uri1')), TestScopedStorageXDirectory( const PlatformScopedStorageXDirectoryCreationParams(uri: 'uri2'), ), @@ -38,11 +33,10 @@ void main() { ]; CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformScopedStorageXDirectory: - (PlatformScopedStorageXDirectoryCreationParams params) => - TestScopedStorageXDirectory( - params, - onList: (ListParams params) => Stream.fromIterable(entities), - ), + (PlatformScopedStorageXDirectoryCreationParams params) => TestScopedStorageXDirectory( + params, + onList: (ListParams params) => Stream.fromIterable(entities), + ), ); final directory = ScopedStorageXDirectory(uri: 'uri'); @@ -62,10 +56,7 @@ void main() { CrossFilePlatform.instance = TestCrossFilePlatform( onCreatePlatformScopedStorageXDirectory: (PlatformScopedStorageXDirectoryCreationParams params) => - TestScopedStorageXDirectory( - params, - onCanRead: () async => canRead, - ), + TestScopedStorageXDirectory(params, onCanRead: () async => canRead), ); final file = ScopedStorageXDirectory(uri: 'uri'); diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart index f33b3597ecd5..085caf778ac7 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart @@ -16,12 +16,8 @@ void main() { test('lastModified', () async { final lastModified = DateTime.now(); CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile( - params, - onLastModified: () async => lastModified, - ), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onLastModified: () async => lastModified), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -32,9 +28,8 @@ void main() { test('length', () async { const length = 42; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile(params, onLength: () async => length), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onLength: () async => length), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -47,12 +42,8 @@ void main() { Uint8List.fromList([5, 6]), ]; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile( - params, - onOpenRead: () => Stream.fromIterable(data), - ), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onOpenRead: () => Stream.fromIterable(data)), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -63,12 +54,8 @@ void main() { test('readAsBytes', () async { final bytes = Uint8List.fromList([1, 2, 3]); CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile( - params, - onReadAsBytes: () async => bytes, - ), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onReadAsBytes: () async => bytes), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -79,13 +66,11 @@ void main() { test('readAsString', () async { const message = 'Hello, World!'; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile( - params, - onReadAsString: ({required Encoding encoding}) async => - message, - ), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile( + params, + onReadAsString: ({required Encoding encoding}) async => message, + ), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -96,9 +81,8 @@ void main() { test('exists', () async { const exists = true; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile(params, onExists: () async => exists), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onExists: () async => exists), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -109,9 +93,8 @@ void main() { test('name', () async { const name = 'name'; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile(params, onName: () async => name), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onName: () async => name), ); final file = ScopedStorageXFile(uri: 'uri'); @@ -122,9 +105,8 @@ void main() { test('canRead', () async { const canRead = false; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformScopedStorageXFile: - (PlatformScopedStorageXFileCreationParams params) => - TestScopedStorageXFile(params, onCanRead: () async => canRead), + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onCanRead: () async => canRead), ); final file = ScopedStorageXFile(uri: 'uri'); diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 401e802bc7ae..28116ffd3af0 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -16,20 +16,14 @@ final class TestCrossFilePlatform extends CrossFilePlatform { this.onCreatePlatformScopedStorageXDirectory, }); - PlatformXFile Function(PlatformXFileCreationParams params)? - onCreatePlatformXFile; + PlatformXFile Function(PlatformXFileCreationParams params)? onCreatePlatformXFile; - PlatformXDirectory Function(PlatformXDirectoryCreationParams params)? - onCreatePlatformXDirectory; + PlatformXDirectory Function(PlatformXDirectoryCreationParams params)? onCreatePlatformXDirectory; - PlatformScopedStorageXFile Function( - PlatformScopedStorageXFileCreationParams params, - )? + PlatformScopedStorageXFile Function(PlatformScopedStorageXFileCreationParams params)? onCreatePlatformScopedStorageXFile; - PlatformScopedStorageXDirectory Function( - PlatformScopedStorageXDirectoryCreationParams params, - )? + PlatformScopedStorageXDirectory Function(PlatformScopedStorageXDirectoryCreationParams params)? onCreatePlatformScopedStorageXDirectory; @override @@ -38,9 +32,7 @@ final class TestCrossFilePlatform extends CrossFilePlatform { } @override - PlatformXDirectory createPlatformXDirectory( - PlatformXDirectoryCreationParams params, - ) { + PlatformXDirectory createPlatformXDirectory(PlatformXDirectoryCreationParams params) { return onCreatePlatformXDirectory?.call(params) ?? TestXDirectory(params); } @@ -48,8 +40,7 @@ final class TestCrossFilePlatform extends CrossFilePlatform { PlatformScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, ) { - return onCreatePlatformScopedStorageXFile?.call(params) ?? - TestScopedStorageXFile(params); + return onCreatePlatformScopedStorageXFile?.call(params) ?? TestScopedStorageXFile(params); } @override @@ -120,8 +111,7 @@ final class TestXFile extends PlatformXFile { } final class TestXDirectory extends PlatformXDirectory { - TestXDirectory(super.params, {this.onExists, this.onList}) - : super.implementation(); + TestXDirectory(super.params, {this.onExists, this.onList}) : super.implementation(); Future Function()? onExists; Stream Function(ListParams params)? onList; @@ -204,14 +194,9 @@ final class TestScopedStorageXFile extends PlatformScopedStorageXFile { } } -final class TestScopedStorageXDirectory - extends PlatformScopedStorageXDirectory { - TestScopedStorageXDirectory( - super.params, { - this.onExists, - this.onList, - this.onCanRead, - }) : super.implementation(); +final class TestScopedStorageXDirectory extends PlatformScopedStorageXDirectory { + TestScopedStorageXDirectory(super.params, {this.onExists, this.onList, this.onCanRead}) + : super.implementation(); Future Function()? onExists; Stream Function(ListParams params)? onList; diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 8098b98b804d..2107c6cbe6f8 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -71,10 +71,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), + appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -105,11 +102,7 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay({ - super.key, - required this.filename, - required this.fileContents, - }); + const TextDisplay({super.key, required this.filename, required this.fileContents}); /// The name of the file. final String filename; @@ -121,14 +114,9 @@ class TextDisplay extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( title: Text(filename), - content: Scrollbar( - child: SingleChildScrollView(child: Text(fileContents)), - ), + content: Scrollbar(child: SingleChildScrollView(child: Text(fileContents))), actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), + TextButton(child: const Text('Close'), onPressed: () => Navigator.pop(context)), ], ); } diff --git a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart index 1e2bf3e55127..51f199cda883 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_library.g.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_library.g.dart @@ -21,11 +21,7 @@ PlatformException _createConnectionError(String channelName) { ); } -List wrapResponse({ - Object? result, - PlatformException? error, - bool empty = false, -}) { +List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; } @@ -45,12 +41,10 @@ List wrapResponse({ @visibleForTesting class PigeonOverrides { /// Overrides [DocumentFile.fromSingleUri]. - static DocumentFile Function({required String singleUri})? - documentFile_fromSingleUri; + static DocumentFile Function({required String singleUri})? documentFile_fromSingleUri; /// Overrides [DocumentFile.fromTreeUri]. - static DocumentFile Function({required String treeUri})? - documentFile_fromTreeUri; + static DocumentFile Function({required String treeUri})? documentFile_fromTreeUri; /// Overrides [ContentResolver.instance]. static ContentResolver? contentResolver_instance; @@ -74,8 +68,7 @@ abstract class PigeonInternalProxyApiBaseClass { PigeonInternalProxyApiBaseClass({ this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + }) : pigeon_instanceManager = pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -145,8 +138,8 @@ class PigeonInstanceManager { // by calling instanceManager.getIdentifier() inside of `==` while this was a // HashMap). final Expando _identifiers = Expando(); - final Map> - _weakInstances = >{}; + final Map> _weakInstances = + >{}; final Map _strongInstances = {}; late final Finalizer _finalizer; @@ -161,8 +154,7 @@ class PigeonInstanceManager { return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); } WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = - _PigeonInternalInstanceManagerApi(); + final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); final PigeonInstanceManager instanceManager = PigeonInstanceManager( @@ -170,18 +162,10 @@ class PigeonInstanceManager { api.removeStrongReference(identifier); }, ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers( - instanceManager: instanceManager, - ); - DocumentFile.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - ContentResolver.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); - InputStream.pigeon_setUpMessageHandlers( - pigeon_instanceManager: instanceManager, - ); + _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); + DocumentFile.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + ContentResolver.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + InputStream.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); return instanceManager; } @@ -198,9 +182,7 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference( - instance, - ); + _weakInstances[identifier] = WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -261,21 +243,15 @@ class PigeonInstanceManager { /// /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference( - int identifier, - ) { - final PigeonInternalProxyApiBaseClass? weakInstance = - _weakInstances[identifier]?.target; + T? getInstanceWithWeakReference(int identifier) { + final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = - _strongInstances[identifier]; + final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance - .pigeon_copy(); + final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); _identifiers[copy] = identifier; - _weakInstances[identifier] = - WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); return copy as T; } @@ -297,10 +273,7 @@ class PigeonInstanceManager { /// /// Throws assertion error if the instance or its identifier has already been /// added. - void addHostCreatedInstance( - PigeonInternalProxyApiBaseClass instance, - int identifier, - ) { + void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); @@ -311,8 +284,7 @@ class PigeonInstanceManager { /// Whether this manager contains the given [identifier]. bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || - _strongInstances.containsKey(identifier); + return _weakInstances.containsKey(identifier) || _strongInstances.containsKey(identifier); } int _nextUniqueIdentifier() { @@ -361,9 +333,7 @@ class _PigeonInternalInstanceManagerApi { 'Argument for dev.flutter.pigeon.cross_file_android.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.', ); try { - (instanceManager ?? PigeonInstanceManager.instance).remove( - arg_identifier!, - ); + (instanceManager ?? PigeonInstanceManager.instance).remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -385,9 +355,7 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [identifier], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -446,9 +414,7 @@ class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { case 128: - return instanceManager.getInstanceWithWeakReference( - readValue(buffer)! as int, - ); + return instanceManager.getInstanceWithWeakReference(readValue(buffer)! as int); default: return super.readValueOfType(type, buffer); } @@ -504,10 +470,8 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String singleUri, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromSingleUri'; @@ -516,9 +480,10 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, singleUri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + singleUri, + ]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -560,21 +525,19 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { super.pigeon_instanceManager, required String treeUri, }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager - .addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.fromTreeUri'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier, treeUri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + treeUri, + ]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { @@ -596,10 +559,7 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// This should only be used by subclasses created by this library or to /// create copies for an [PigeonInstanceManager]. @protected - DocumentFile.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); + DocumentFile.pigeon_detached({super.pigeon_binaryMessenger, super.pigeon_instanceManager}); late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecDocumentFile = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); @@ -610,10 +570,9 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { PigeonInstanceManager? pigeon_instanceManager, DocumentFile Function()? pigeon_newInstance, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( @@ -636,15 +595,14 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { 'Argument for dev.flutter.pigeon.cross_file_android.DocumentFile.pigeon_newInstance was null, expected non-null int.', ); try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - DocumentFile.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + (pigeon_instanceManager ?? PigeonInstanceManager.instance).addHostCreatedInstance( + pigeon_newInstance?.call() ?? + DocumentFile.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -660,19 +618,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Indicates whether the current context is allowed to read from this file. Future canRead() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.canRead'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.canRead'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -694,19 +648,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Deletes this file. Future delete() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.delete'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.delete'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -728,19 +678,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Returns a boolean indicating whether this file can be found. Future exists() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.exists'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.exists'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -763,19 +709,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Returns the time when this file was last modified, measured in /// milliseconds since January 1st, 1970, midnight. Future lastModified() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.lastModified'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -797,19 +739,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Returns the length of this file in bytes. Future length() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.length'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.length'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -831,19 +769,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Indicates if this file represents a *file*. Future isFile() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.isFile'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.isFile'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -865,19 +799,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Indicates if this file represents a *directory*. Future isDirectory() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.isDirectory'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -900,19 +830,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Returns an list of files contained in the directory represented by this /// file. Future> listFiles() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.listFiles'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -934,19 +860,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// A Uri for the underlying document represented by this file. Future getUri() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.getUri'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.getUri'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -968,19 +890,15 @@ class DocumentFile extends PigeonInternalProxyApiBaseClass { /// Returns the display name of this document. Future getName() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecDocumentFile; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecDocumentFile; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.DocumentFile.getName'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.DocumentFile.getName'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1013,10 +931,7 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { /// This should only be used by subclasses created by this library or to /// create copies for an [PigeonInstanceManager]. @protected - ContentResolver.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); + ContentResolver.pigeon_detached({super.pigeon_binaryMessenger, super.pigeon_instanceManager}); late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecContentResolver = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); @@ -1027,8 +942,7 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { /// Helper field for accessing the `ContentResolver` from the current Android /// `Context`. - static ContentResolver get instance => - PigeonOverrides.contentResolver_instance ?? _instance; + static ContentResolver get instance => PigeonOverrides.contentResolver_instance ?? _instance; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, @@ -1036,10 +950,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { PigeonInstanceManager? pigeon_instanceManager, ContentResolver Function()? pigeon_newInstance, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( @@ -1062,15 +975,14 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { 'Argument for dev.flutter.pigeon.cross_file_android.ContentResolver.pigeon_newInstance was null, expected non-null int.', ); try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - ContentResolver.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + (pigeon_instanceManager ?? PigeonInstanceManager.instance).addHostCreatedInstance( + pigeon_newInstance?.call() ?? + ContentResolver.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1085,14 +997,15 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { } static ContentResolver pigeonVar_instance() { - final ContentResolver pigeonVar_instance = - ContentResolver.pigeon_detached(); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); + final ContentResolver pigeonVar_instance = ContentResolver.pigeon_detached(); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + PigeonInstanceManager.instance, + ); final BinaryMessenger pigeonVar_binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger; - final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance - .addDartCreatedInstance(pigeonVar_instance); + final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance.addDartCreatedInstance( + pigeonVar_instance, + ); () async { const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.ContentResolver.instance'; @@ -1101,9 +1014,9 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [pigeonVar_instanceIdentifier], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1122,8 +1035,7 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { /// Open a stream on to the content associated with a content URI. Future openInputStream(String uri) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecContentResolver; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecContentResolver; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.ContentResolver.openInputStream'; @@ -1132,9 +1044,7 @@ class ContentResolver extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, uri], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this, uri]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1168,10 +1078,7 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// This should only be used by subclasses created by this library or to /// create copies for an [PigeonInstanceManager]. @protected - InputStream.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); + InputStream.pigeon_detached({super.pigeon_binaryMessenger, super.pigeon_instanceManager}); late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecInputStream = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); @@ -1182,10 +1089,9 @@ class InputStream extends PigeonInternalProxyApiBaseClass { PigeonInstanceManager? pigeon_instanceManager, InputStream Function()? pigeon_newInstance, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( @@ -1208,15 +1114,14 @@ class InputStream extends PigeonInternalProxyApiBaseClass { 'Argument for dev.flutter.pigeon.cross_file_android.InputStream.pigeon_newInstance was null, expected non-null int.', ); try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( - pigeon_newInstance?.call() ?? - InputStream.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - ), - arg_pigeon_instanceIdentifier!, - ); + (pigeon_instanceManager ?? PigeonInstanceManager.instance).addHostCreatedInstance( + pigeon_newInstance?.call() ?? + InputStream.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); @@ -1233,19 +1138,15 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// Reads some number of bytes from the input stream and stores them into the /// returns them. Future readBytes(int len) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecInputStream; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.InputStream.readBytes'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.InputStream.readBytes'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, len], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this, len]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1267,19 +1168,15 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// Reads all remaining bytes from the input stream. Future readAllBytes() async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecInputStream; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.InputStream.readAllBytes'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); @@ -1301,19 +1198,15 @@ class InputStream extends PigeonInternalProxyApiBaseClass { /// Skips over and discards n bytes of data from this input stream. Future skip(int n) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecInputStream; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecInputStream; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_android.InputStream.skip'; + const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_android.InputStream.skip'; final pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send( - [this, n], - ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([this, n]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; if (pigeonVar_replyList == null) { throw _createConnectionError(pigeonVar_channelName); diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index 691d73fce195..9303e9e76cd9 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -8,14 +8,11 @@ import 'android_library.g.dart'; import 'android_scoped_storage_cross_file.dart'; /// Implementation of [PlatformScopedStorageXDirectory] for iOS and macOS. -base class AndroidScopedStorageXDirectory - extends PlatformScopedStorageXDirectory { +base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirectory { /// Constructs an [AndroidScopedStorageXDirectory]. AndroidScopedStorageXDirectory(super.params) : super.implementation(); - late final DocumentFile _documentFile = DocumentFile.fromTreeUri( - treeUri: params.uri, - ); + late final DocumentFile _documentFile = DocumentFile.fromTreeUri(treeUri: params.uri); @override Future canRead() => _documentFile.canRead(); @@ -30,9 +27,7 @@ base class AndroidScopedStorageXDirectory for (final DocumentFile documentFile in await _documentFile.listFiles()) { final String uri = await documentFile.getUri(); if (await documentFile.isFile()) { - yield AndroidScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: uri), - ); + yield AndroidScopedStorageXFile(PlatformScopedStorageXFileCreationParams(uri: uri)); } else if (await documentFile.isDirectory()) { yield AndroidScopedStorageXDirectory( PlatformScopedStorageXDirectoryCreationParams(uri: uri), diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index c127b71108a1..8fa55688f731 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -16,11 +16,11 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { /// Constructs an [AndroidScopedStorageXFile]. AndroidScopedStorageXFile(super.params) : super.implementation(); - late final android.DocumentFile _documentFile = - android.DocumentFile.fromSingleUri(singleUri: params.uri); + late final android.DocumentFile _documentFile = android.DocumentFile.fromSingleUri( + singleUri: params.uri, + ); - late final android.ContentResolver _contentResolver = - android.ContentResolver.instance; + late final android.ContentResolver _contentResolver = android.ContentResolver.instance; /// Maximum number of bytes to read at a time from the native Android /// InputStream. @@ -59,8 +59,7 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { int bytesToRead = (end ?? fileLength) - (start ?? 0); assert(bytesToRead >= 0); - final android.InputStream? inputStream = await _contentResolver - .openInputStream(params.uri); + final android.InputStream? inputStream = await _contentResolver.openInputStream(params.uri); if (inputStream case final android.InputStream inputStream) { if (start != null && start > 0) { @@ -80,8 +79,7 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { @override Future readAsBytes() async { - final android.InputStream? inputStream = await _contentResolver - .openInputStream(params.uri); + final android.InputStream? inputStream = await _contentResolver.openInputStream(params.uri); if (inputStream case final android.InputStream inputStream) { return inputStream.readAllBytes(); } diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index 2070a2250d6a..6e68926cd92b 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -11,9 +11,7 @@ import 'package:pigeon/pigeon.dart'; dartOut: 'lib/src/android_library.g.dart', kotlinOut: 'android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt', - kotlinOptions: KotlinOptions( - package: 'dev.flutter.packages.cross_file_android.proxies', - ), + kotlinOptions: KotlinOptions(package: 'dev.flutter.packages.cross_file_android.proxies'), copyrightHeader: 'pigeons/copyright.txt', ), ) @@ -70,11 +68,7 @@ abstract class DocumentFile { /// This class provides applications access to the content model. /// /// See https://developer.android.com/reference/kotlin/android/content/ContentResolver -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions( - fullClassName: 'android.content.ContentResolver', - ), -) +@ProxyApi(kotlinOptions: KotlinProxyApiOptions(fullClassName: 'android.content.ContentResolver')) abstract class ContentResolver { /// Helper field for accessing the `ContentResolver` from the current Android /// `Context`. @@ -89,9 +83,7 @@ abstract class ContentResolver { /// stream of bytes. /// /// See https://developer.android.com/reference/java/io/InputStream. -@ProxyApi( - kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream'), -) +@ProxyApi(kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream')) abstract class InputStream { /// Reads some number of bytes from the input stream and stores them into the /// returns them. diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart index 125141be7e68..ea92c4d51763 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart @@ -25,11 +25,10 @@ void main() { when(mockDocumentFile.isDirectory()).thenAnswer((_) async => true); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromTreeUri = - ({required String treeUri}) { - expect(treeUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromTreeUri = ({required String treeUri}) { + expect(treeUri, uri); + return mockDocumentFile; + }; final directory = AndroidScopedStorageXDirectory( const PlatformScopedStorageXDirectoryCreationParams(uri: uri), @@ -44,11 +43,10 @@ void main() { when(mockDocumentFile.canRead()).thenAnswer((_) async => canRead); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromTreeUri = - ({required String treeUri}) { - expect(treeUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromTreeUri = ({required String treeUri}) { + expect(treeUri, uri); + return mockDocumentFile; + }; final directory = AndroidScopedStorageXDirectory( const PlatformScopedStorageXDirectoryCreationParams(uri: uri), @@ -68,17 +66,15 @@ void main() { when(mockDirectory.listFiles()).thenAnswer((_) async => files); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromTreeUri = - ({required String treeUri}) { - expect(treeUri, uri); - return mockDirectory; - }; - - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, fileUri); - return mockFile; - }; + android.PigeonOverrides.documentFile_fromTreeUri = ({required String treeUri}) { + expect(treeUri, uri); + return mockDirectory; + }; + + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, fileUri); + return mockFile; + }; final dir = AndroidScopedStorageXDirectory( const PlatformScopedStorageXDirectoryCreationParams(uri: uri), diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart index f4bac06e92f6..52af6b8ff85f 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.mocks.dart @@ -24,15 +24,13 @@ import 'package:mockito/src/dummies.dart' as _i4; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { +class _FakePigeonInstanceManager_0 extends _i1.SmartFake implements _i2.PigeonInstanceManager { _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } class _FakeDocumentFile_1 extends _i1.SmartFake implements _i2.DocumentFile { - _FakeDocumentFile_1(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); + _FakeDocumentFile_1(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } /// A class which mocks [DocumentFile]. @@ -88,10 +86,7 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { @override _i3.Future length() => - (super.noSuchMethod( - Invocation.method(#length, []), - returnValue: _i3.Future.value(0), - ) + (super.noSuchMethod(Invocation.method(#length, []), returnValue: _i3.Future.value(0)) as _i3.Future); @override @@ -114,9 +109,7 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { _i3.Future> listFiles() => (super.noSuchMethod( Invocation.method(#listFiles, []), - returnValue: _i3.Future>.value( - <_i2.DocumentFile>[], - ), + returnValue: _i3.Future>.value(<_i2.DocumentFile>[]), ) as _i3.Future>); @@ -132,20 +125,14 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { @override _i3.Future getName() => - (super.noSuchMethod( - Invocation.method(#getName, []), - returnValue: _i3.Future.value(), - ) + (super.noSuchMethod(Invocation.method(#getName, []), returnValue: _i3.Future.value()) as _i3.Future); @override _i2.DocumentFile pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeDocumentFile_1( - this, - Invocation.method(#pigeon_copy, []), - ), + returnValue: _FakeDocumentFile_1(this, Invocation.method(#pigeon_copy, [])), ) as _i2.DocumentFile); } diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart index 8eb575acab8b..9db438f03b14 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart @@ -14,11 +14,7 @@ import 'package:mockito/mockito.dart'; import 'android_scoped_storage_cross_file_test.mocks.dart'; -@GenerateMocks([ - android.ContentResolver, - android.DocumentFile, - android.InputStream, -]) +@GenerateMocks([android.ContentResolver, android.DocumentFile, android.InputStream]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -32,20 +28,16 @@ void main() { when(mockDocumentFile.lastModified()).thenAnswer((_) async => lastModified); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final file = AndroidScopedStorageXFile( const PlatformScopedStorageXFileCreationParams(uri: uri), ); - expect( - await file.lastModified(), - DateTime.fromMillisecondsSinceEpoch(lastModified), - ); + expect(await file.lastModified(), DateTime.fromMillisecondsSinceEpoch(lastModified)); }); test('length', () async { @@ -54,11 +46,10 @@ void main() { when(mockDocumentFile.length()).thenAnswer((_) async => length); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final file = AndroidScopedStorageXFile( const PlatformScopedStorageXFileCreationParams(uri: uri), @@ -75,19 +66,16 @@ void main() { when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final mockInputStream = MockInputStream(); setUpInputStreamWithBytes(mockInputStream, testBytes); final mockContentResolver = MockContentResolver(); - when( - mockContentResolver.openInputStream(uri), - ).thenAnswer((_) async => mockInputStream); + when(mockContentResolver.openInputStream(uri)).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; final file = AndroidScopedStorageXFile( @@ -97,41 +85,33 @@ void main() { expect(combineLists(await file.openRead().toList()), testBytes); }); - test( - 'openRead finishes successfully with file larger than max array len', - () async { - final testBytes = Uint8List.fromList( - List.filled(AndroidScopedStorageXFile.maxByteArrayLen + 1, 0), - ); - - final mockDocumentFile = MockDocumentFile(); - when( - mockDocumentFile.length(), - ).thenAnswer((_) async => testBytes.length); - - const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; - - final mockInputStream = MockInputStream(); - setUpInputStreamWithBytes(mockInputStream, testBytes); - - final mockContentResolver = MockContentResolver(); - when( - mockContentResolver.openInputStream(uri), - ).thenAnswer((_) async => mockInputStream); - android.PigeonOverrides.contentResolver_instance = mockContentResolver; - - final file = AndroidScopedStorageXFile( - const PlatformScopedStorageXFileCreationParams(uri: uri), - ); - - expect(combineLists(await file.openRead().toList()), testBytes); - }, - ); + test('openRead finishes successfully with file larger than max array len', () async { + final testBytes = Uint8List.fromList( + List.filled(AndroidScopedStorageXFile.maxByteArrayLen + 1, 0), + ); + + final mockDocumentFile = MockDocumentFile(); + when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); + + const uri = 'uri'; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; + + final mockInputStream = MockInputStream(); + setUpInputStreamWithBytes(mockInputStream, testBytes); + + final mockContentResolver = MockContentResolver(); + when(mockContentResolver.openInputStream(uri)).thenAnswer((_) async => mockInputStream); + android.PigeonOverrides.contentResolver_instance = mockContentResolver; + + final file = AndroidScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: uri), + ); + + expect(combineLists(await file.openRead().toList()), testBytes); + }); test('openRead finishes successfully with subset of array', () async { final testBytes = Uint8List.fromList([0, 0, 0, 1, 1, 1, 0, 0, 0]); @@ -140,19 +120,16 @@ void main() { when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final mockInputStream = MockInputStream(); setUpInputStreamWithBytes(mockInputStream, testBytes); final mockContentResolver = MockContentResolver(); - when( - mockContentResolver.openInputStream(uri), - ).thenAnswer((_) async => mockInputStream); + when(mockContentResolver.openInputStream(uri)).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; final file = AndroidScopedStorageXFile( @@ -170,19 +147,16 @@ void main() { when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final mockInputStream = MockInputStream(); when(mockInputStream.readAllBytes()).thenAnswer((_) async => testBytes); final mockContentResolver = MockContentResolver(); - when( - mockContentResolver.openInputStream(uri), - ).thenAnswer((_) async => mockInputStream); + when(mockContentResolver.openInputStream(uri)).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; final file = AndroidScopedStorageXFile( @@ -200,19 +174,16 @@ void main() { when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final mockInputStream = MockInputStream(); setUpInputStreamWithBytes(mockInputStream, testBytes); final mockContentResolver = MockContentResolver(); - when( - mockContentResolver.openInputStream(uri), - ).thenAnswer((_) async => mockInputStream); + when(mockContentResolver.openInputStream(uri)).thenAnswer((_) async => mockInputStream); android.PigeonOverrides.contentResolver_instance = mockContentResolver; final file = AndroidScopedStorageXFile( @@ -228,11 +199,10 @@ void main() { when(mockDocumentFile.canRead()).thenAnswer((_) async => canRead); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final file = AndroidScopedStorageXFile( const PlatformScopedStorageXFileCreationParams(uri: uri), @@ -247,11 +217,10 @@ void main() { when(mockDocumentFile.isFile()).thenAnswer((_) async => true); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final file = AndroidScopedStorageXFile( const PlatformScopedStorageXFileCreationParams(uri: uri), @@ -266,11 +235,10 @@ void main() { when(mockDocumentFile.getName()).thenAnswer((_) async => name); const uri = 'uri'; - android.PigeonOverrides.documentFile_fromSingleUri = - ({required String singleUri}) { - expect(singleUri, uri); - return mockDocumentFile; - }; + android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { + expect(singleUri, uri); + return mockDocumentFile; + }; final file = AndroidScopedStorageXFile( const PlatformScopedStorageXFileCreationParams(uri: uri), @@ -280,10 +248,7 @@ void main() { }); } -void setUpInputStreamWithBytes( - MockInputStream mockInputStream, - Uint8List bytes, -) { +void setUpInputStreamWithBytes(MockInputStream mockInputStream, Uint8List bytes) { Iterable remainingBytes = bytes.toList(); when(mockInputStream.skip(any)).thenAnswer((Invocation invocation) async { @@ -299,9 +264,7 @@ void setUpInputStreamWithBytes( return diff; }); - when(mockInputStream.readBytes(any)).thenAnswer(( - Invocation invocation, - ) async { + when(mockInputStream.readBytes(any)).thenAnswer((Invocation invocation) async { final len = invocation.positionalArguments[0] as int; final List bytesRead = remainingBytes.take(len).toList(); @@ -312,7 +275,5 @@ void setUpInputStreamWithBytes( } Uint8List combineLists(List lists) { - return Uint8List.fromList( - lists.expand((Uint8List element) => element).toList(), - ); + return Uint8List.fromList(lists.expand((Uint8List element) => element).toList()); } diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart index 8694dd65dee7..fa72c9578558 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.mocks.dart @@ -25,26 +25,22 @@ import 'package:mockito/src/dummies.dart' as _i4; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { +class _FakePigeonInstanceManager_0 extends _i1.SmartFake implements _i2.PigeonInstanceManager { _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeContentResolver_1 extends _i1.SmartFake - implements _i2.ContentResolver { +class _FakeContentResolver_1 extends _i1.SmartFake implements _i2.ContentResolver { _FakeContentResolver_1(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } class _FakeDocumentFile_2 extends _i1.SmartFake implements _i2.DocumentFile { - _FakeDocumentFile_2(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); + _FakeDocumentFile_2(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } class _FakeInputStream_3 extends _i1.SmartFake implements _i2.InputStream { - _FakeInputStream_3(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); + _FakeInputStream_3(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } /// A class which mocks [ContentResolver]. @@ -78,10 +74,7 @@ class MockContentResolver extends _i1.Mock implements _i2.ContentResolver { _i2.ContentResolver pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeContentResolver_1( - this, - Invocation.method(#pigeon_copy, []), - ), + returnValue: _FakeContentResolver_1(this, Invocation.method(#pigeon_copy, [])), ) as _i2.ContentResolver); } @@ -139,10 +132,7 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { @override _i3.Future length() => - (super.noSuchMethod( - Invocation.method(#length, []), - returnValue: _i3.Future.value(0), - ) + (super.noSuchMethod(Invocation.method(#length, []), returnValue: _i3.Future.value(0)) as _i3.Future); @override @@ -165,9 +155,7 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { _i3.Future> listFiles() => (super.noSuchMethod( Invocation.method(#listFiles, []), - returnValue: _i3.Future>.value( - <_i2.DocumentFile>[], - ), + returnValue: _i3.Future>.value(<_i2.DocumentFile>[]), ) as _i3.Future>); @@ -183,20 +171,14 @@ class MockDocumentFile extends _i1.Mock implements _i2.DocumentFile { @override _i3.Future getName() => - (super.noSuchMethod( - Invocation.method(#getName, []), - returnValue: _i3.Future.value(), - ) + (super.noSuchMethod(Invocation.method(#getName, []), returnValue: _i3.Future.value()) as _i3.Future); @override _i2.DocumentFile pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeDocumentFile_2( - this, - Invocation.method(#pigeon_copy, []), - ), + returnValue: _FakeDocumentFile_2(this, Invocation.method(#pigeon_copy, [])), ) as _i2.DocumentFile); } @@ -238,20 +220,14 @@ class MockInputStream extends _i1.Mock implements _i2.InputStream { @override _i3.Future skip(int? n) => - (super.noSuchMethod( - Invocation.method(#skip, [n]), - returnValue: _i3.Future.value(0), - ) + (super.noSuchMethod(Invocation.method(#skip, [n]), returnValue: _i3.Future.value(0)) as _i3.Future); @override _i2.InputStream pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeInputStream_3( - this, - Invocation.method(#pigeon_copy, []), - ), + returnValue: _FakeInputStream_3(this, Invocation.method(#pigeon_copy, [])), ) as _i2.InputStream); } diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift index 405bada8def5..91fb17a68399 100644 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift @@ -4,6 +4,8 @@ import XCTest +@testable import cross_file_darwin + #if os(iOS) import Flutter #elseif os(macOS) @@ -12,16 +14,14 @@ import XCTest #error("Unsupported platform.") #endif -@testable import cross_file_darwin - class TestProxyApiRegistrar: ProxyAPIRegistrar { init() { super.init( - binaryMessenger: TestBinaryMessenger()) + binaryMessenger: TestBinaryMessenger()) } override func dispatchOnMainThread( - execute work: @escaping (@escaping (String, PigeonError) -> Void) -> Void + execute work: @escaping (@escaping (String, PigeonError) -> Void) -> Void ) { work { _, _ in } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift index b5ed1e6484c5..7b854e856e7f 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift @@ -30,7 +30,7 @@ class AssetResourceReader { self.delegate?.onCompletion(reader: self, error: error?.localizedDescription) } } - + return true } } @@ -49,7 +49,6 @@ protocol AssetResourceReaderDelegate { /// `PHAssetResourceManager.requestDataForAssetResource`. func onDataReceived(reader: AssetResourceReader, bytes: Data) - /// Start reading bytes from the asset with the given identifier. /// /// Returns false if the resource for the identifier could not be accessed or diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 4cddbba96b33..232759a2f8ad 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -59,7 +59,9 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") } private func isNullish(_ value: Any?) -> Bool { @@ -77,7 +79,6 @@ protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { func onDeinit(identifier: Int64) } - // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -93,14 +94,18 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, + delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( + identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = + objc_getAssociatedObject(instance, associatedObjectKey) + as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -112,7 +117,6 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } - /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -216,7 +220,8 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -297,7 +302,6 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } - private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -310,9 +314,15 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, + instanceManager: CrossFileDarwinApisPigeonInstanceManager? + ) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -327,7 +337,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -343,9 +355,13 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -365,7 +381,8 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiAssetResourceReader] used to add a new Dart instance of /// `AssetResourceReader` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceReader + func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiAssetResourceReader } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -378,12 +395,15 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + private class InstanceManagerApiFinalizerDelegate: + CrossFileDarwinApisPigeonInternalFinalizerDelegate + { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -397,7 +417,9 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + init( + binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + ) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -406,18 +428,25 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiAssetResourceReader.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: + FlutterStandardReaderWriter +{ unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: + CrossFileDarwinApisPigeonCodecReader + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -441,7 +470,9 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: + CrossFileDarwinApisPigeonCodecWriter + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -450,24 +481,26 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + { super.writeValue(value) return } - if let instance = value as? AssetResourceReader { pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReader(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -485,11 +518,13 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( + data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( + data: data, pigeonRegistrar: pigeonRegistrar) } } @@ -510,11 +545,13 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } protocol PigeonApiDelegateAssetResourceReader { - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws -> AssetResourceReader + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws + -> AssetResourceReader /// Start reading bytes from the asset with the given identifier. /// /// Returns false if the resource for the identifier could not be accessed or @@ -522,7 +559,10 @@ protocol PigeonApiDelegateAssetResourceReader { /// /// Bytes are passed to `onDataReceived` and the request is completed when /// `onCompletion` is called. - func startRead(pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, localIdentifier: String) throws -> Bool + func startRead( + pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, + localIdentifier: String + ) throws -> Bool } protocol PigeonApiProtocolAssetResourceReader { @@ -532,38 +572,50 @@ protocol PigeonApiProtocolAssetResourceReader { /// /// Corresponds to the `dataReceivedHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) + func onDataReceived( + pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, + completion: @escaping (Result) -> Void) /// Indicates the request for data has completed. /// /// Called once after the request has been fulfilled or has failed. /// /// Corresponds to the `completionHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, completion: @escaping (Result) -> Void) + func onCompletion( + pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, + completion: @escaping (Result) -> Void) } -final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { +final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateAssetResourceReader - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateAssetResourceReader) { + init( + pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateAssetResourceReader + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", binaryMessenger: binaryMessenger, codec: codec) + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { pigeonDefaultConstructorChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( -try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), -withIdentifier: pigeonIdentifierArg) + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -572,14 +624,17 @@ withIdentifier: pigeonIdentifierArg) } else { pigeonDefaultConstructorChannel.setMessageHandler(nil) } - let startReadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead", binaryMessenger: binaryMessenger, codec: codec) + let startReadChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { startReadChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! AssetResourceReader let localIdentifierArg = args[1] as! String do { - let result = try api.pigeonDelegate.startRead(pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) + let result = try api.pigeonDelegate.startRead( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -591,21 +646,25 @@ withIdentifier: pigeonIdentifierArg) } ///Creates a Dart instance of AssetResourceReader and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { + } else { completion( .failure( PigeonError( code: "new-instance-error", - message: "Error: Attempting to create a new Dart instance of AssetResourceReader, but the class has a nonnull callback method.", details: ""))) + message: + "Error: Attempting to create a new Dart instance of AssetResourceReader, but the class has a nonnull callback method.", + details: ""))) } } /// Provides the requested data. @@ -614,7 +673,10 @@ withIdentifier: pigeonIdentifierArg) /// /// Corresponds to the `dataReceivedHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { + func onDataReceived( + pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -622,18 +684,22 @@ withIdentifier: pigeonIdentifierArg) code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: "Callback to `AssetResourceReader.onDataReceived` failed because native instance was not in the instance manager.", details: ""))) + message: + "Callback to `AssetResourceReader.onDataReceived` failed because native instance was not in the instance manager.", + details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, bytesArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -656,7 +722,10 @@ withIdentifier: pigeonIdentifierArg) /// /// Corresponds to the `completionHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, completion: @escaping (Result) -> Void) { + func onCompletion( + pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -664,18 +733,22 @@ withIdentifier: pigeonIdentifierArg) code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: "Callback to `AssetResourceReader.onCompletion` failed because native instance was not in the instance manager.", details: ""))) + message: + "Callback to `AssetResourceReader.onCompletion` failed because native instance was not in the instance manager.", + details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, errorArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 6ef0db20ba87..cfcec044e0d3 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -7,13 +7,6 @@ environment: flutter: ">=3.38.0" dependencies: - cross_file_darwin: - # When depending on this package from a real application you should use: - # cross_file_darwin: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ cupertino_icons: ^1.0.8 file_selector: git: diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 58477b821bd1..f360e28c9d94 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -15,9 +15,9 @@ import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, + List? replyList, + String channelName, { + required bool isNullValid, }) { if (replyList == null) { throw PlatformException( @@ -39,7 +39,6 @@ Object? _extractReplyValueOrThrow( return replyList.firstOrNull; } - List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; @@ -49,6 +48,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -60,15 +60,10 @@ List wrapResponse({Object? result, PlatformException? error, bool empty class PigeonOverrides { /// Overrides [AssetResourceReader.new]. static AssetResourceReader Function({ - required void Function( - AssetResourceReader pigeon_instance, - Uint8List bytes, - ) onDataReceived, - required void Function( - AssetResourceReader pigeon_instance, - String? error, - ) onCompletion, - })? assetResourceReader_new; + required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, + required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, + })? + assetResourceReader_new; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { @@ -87,8 +82,7 @@ abstract class PigeonInternalProxyApiBaseClass { PigeonInternalProxyApiBaseClass({ this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + }) : pigeon_instanceManager = pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -160,7 +154,8 @@ class PigeonInstanceManager { final Expando _identifiers = Expando(); final Map> _weakInstances = >{}; - final Map _strongInstances = {}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -199,8 +194,7 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -302,8 +296,7 @@ class PigeonInstanceManager { /// Whether this manager contains the given [identifier]. bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || - _strongInstances.containsKey(identifier); + return _weakInstances.containsKey(identifier) || _strongInstances.containsKey(identifier); } int _nextUniqueIdentifier() { @@ -320,7 +313,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -333,9 +326,10 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { @@ -343,14 +337,14 @@ class _PigeonInternalInstanceManagerApi { final List args = message! as List; final int arg_identifier = args[0]! as int; try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier); + (instanceManager ?? PigeonInstanceManager.instance).remove(arg_identifier); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -365,15 +359,10 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); } /// Clear the native `PigeonInstanceManager`. @@ -390,39 +379,33 @@ class _PigeonInternalInstanceManagerApi { final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); } } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -444,20 +427,15 @@ class _PigeonCodec extends StandardMessageCodec { } } } + /// Class for handling an instance of asynchronously reading bytes from /// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). class AssetResourceReader extends PigeonInternalProxyApiBaseClass { factory AssetResourceReader({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - required void Function( - AssetResourceReader pigeon_instance, - Uint8List bytes, - ) onDataReceived, - required void Function( - AssetResourceReader pigeon_instance, - String? error, - ) onCompletion, + required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, + required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, }) { if (PigeonOverrides.assetResourceReader_new != null) { return PigeonOverrides.assetResourceReader_new!( @@ -480,10 +458,8 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { required this.onDataReceived, required this.onCompletion, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceReader; + final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor'; @@ -492,16 +468,13 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + ]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); }(); } @@ -517,8 +490,7 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { required this.onCompletion, }); - late final _PigeonInternalProxyApiBaseCodec - _pigeonVar_codecAssetResourceReader = + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceReader = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); /// Provides the requested data. @@ -545,10 +517,7 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function( - AssetResourceReader pigeon_instance, - Uint8List bytes, - ) onDataReceived; + final void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived; /// Indicates the request for data has completed. /// @@ -574,50 +543,44 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function( - AssetResourceReader pigeon_instance, - String? error, - ) onCompletion; + final void Function(AssetResourceReader pigeon_instance, String? error) onCompletion; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - void Function( - AssetResourceReader pigeon_instance, - Uint8List bytes, - )? onDataReceived, - void Function( - AssetResourceReader pigeon_instance, - String? error, - )? onCompletion, + void Function(AssetResourceReader pigeon_instance, Uint8List bytes)? onDataReceived, + void Function(AssetResourceReader pigeon_instance, String? error)? onCompletion, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; - final AssetResourceReader arg_pigeon_instance = - args[0]! as AssetResourceReader; + final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; final Uint8List arg_bytes = args[1]! as Uint8List; try { - (onDataReceived ?? arg_pigeon_instance.onDataReceived) - .call(arg_pigeon_instance, arg_bytes); + (onDataReceived ?? arg_pigeon_instance.onDataReceived).call( + arg_pigeon_instance, + arg_bytes, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -625,26 +588,26 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { pigeonVar_channel.setMessageHandler((Object? message) async { final List args = message! as List; - final AssetResourceReader arg_pigeon_instance = - args[0]! as AssetResourceReader; + final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; final String? arg_error = args[1] as String?; try { - (onCompletion ?? arg_pigeon_instance.onCompletion) - .call(arg_pigeon_instance, arg_error); + (onCompletion ?? arg_pigeon_instance.onCompletion).call(arg_pigeon_instance, arg_error); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -659,8 +622,7 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// Bytes are passed to `onDataReceived` and the request is completed when /// `onCompletion` is called. Future startRead(String localIdentifier) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceReader; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead'; @@ -669,8 +631,10 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, localIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + this, + localIdentifier, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( @@ -691,4 +655,3 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { ); } } - diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart index f2b37b39bf0f..cb302e37f3cb 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart @@ -24,14 +24,12 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { +class _FakePigeonInstanceManager_0 extends _i1.SmartFake implements _i2.PigeonInstanceManager { _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeAssetResourceReader_1 extends _i1.SmartFake - implements _i2.AssetResourceReader { +class _FakeAssetResourceReader_1 extends _i1.SmartFake implements _i2.AssetResourceReader { _FakeAssetResourceReader_1(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } @@ -39,8 +37,7 @@ class _FakeAssetResourceReader_1 extends _i1.SmartFake /// A class which mocks [AssetResourceReader]. /// /// See the documentation for Mockito's code generation for more information. -class MockAssetResourceReader extends _i1.Mock - implements _i2.AssetResourceReader { +class MockAssetResourceReader extends _i1.Mock implements _i2.AssetResourceReader { MockAssetResourceReader() { _i1.throwOnMissingStub(this); } @@ -49,11 +46,7 @@ class MockAssetResourceReader extends _i1.Mock void Function(_i2.AssetResourceReader, _i3.Uint8List) get onDataReceived => (super.noSuchMethod( Invocation.getter(#onDataReceived), - returnValue: - ( - _i2.AssetResourceReader pigeon_instance, - _i3.Uint8List bytes, - ) {}, + returnValue: (_i2.AssetResourceReader pigeon_instance, _i3.Uint8List bytes) {}, ) as void Function(_i2.AssetResourceReader, _i3.Uint8List)); @@ -61,8 +54,7 @@ class MockAssetResourceReader extends _i1.Mock void Function(_i2.AssetResourceReader, String?) get onCompletion => (super.noSuchMethod( Invocation.getter(#onCompletion), - returnValue: - (_i2.AssetResourceReader pigeon_instance, String? error) {}, + returnValue: (_i2.AssetResourceReader pigeon_instance, String? error) {}, ) as void Function(_i2.AssetResourceReader, String?)); @@ -89,10 +81,7 @@ class MockAssetResourceReader extends _i1.Mock _i2.AssetResourceReader pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeAssetResourceReader_1( - this, - Invocation.method(#pigeon_copy, []), - ), + returnValue: _FakeAssetResourceReader_1(this, Invocation.method(#pigeon_copy, [])), ) as _i2.AssetResourceReader); } diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart index 9455cfbad20e..3d04b30c42d7 100644 --- a/packages/cross_file/cross_file_io/example/lib/main.dart +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -68,10 +68,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), + appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -102,11 +99,7 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay({ - super.key, - required this.filename, - required this.fileContents, - }); + const TextDisplay({super.key, required this.filename, required this.fileContents}); /// The name of the file. final String filename; @@ -118,14 +111,9 @@ class TextDisplay extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( title: Text(filename), - content: Scrollbar( - child: SingleChildScrollView(child: Text(fileContents)), - ), + content: Scrollbar(child: SingleChildScrollView(child: Text(fileContents))), actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), + TextButton(child: const Text('Close'), onPressed: () => Navigator.pop(context)), ], ); } diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index ce084ca77716..3ca189ee7e24 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -3,11 +3,7 @@ // found in the LICENSE file. export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show - ListParams, - PlatformXDirectoryCreationParams, - PlatformXEntity, - PlatformXFileCreationParams; + show ListParams, PlatformXDirectoryCreationParams, PlatformXEntity, PlatformXFileCreationParams; export 'src/cross_file_io.dart'; export 'src/io_cross_directory.dart'; diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index bf0368a28397..8d0126ca12d2 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -15,8 +15,7 @@ base class CrossFileIO extends CrossFilePlatform { } /// Whether the current implementation of `cross_file` is [CrossFileIO]. - static bool isCurrentImplementation() => - CrossFilePlatform.instance.runtimeType == CrossFileIO; + static bool isCurrentImplementation() => CrossFilePlatform.instance.runtimeType == CrossFileIO; @override IOXFile createPlatformXFile(PlatformXFileCreationParams params) { @@ -24,9 +23,7 @@ base class CrossFileIO extends CrossFilePlatform { } @override - IOXDirectory createPlatformXDirectory( - PlatformXDirectoryCreationParams params, - ) { + IOXDirectory createPlatformXDirectory(PlatformXDirectoryCreationParams params) { return IOXDirectory(params); } } diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart index 499522048edb..a529a13197a2 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -17,13 +17,10 @@ base class IOXDirectoryCreationParams extends PlatformXDirectoryCreationParams { : this.fromDirectory(Directory.fromUri(Uri.parse(uri))); /// Constructs an [IOXDirectoryCreationParams] from a [Directory]. - IOXDirectoryCreationParams.fromDirectory(this.directory) - : super(uri: directory.uri.toString()); + IOXDirectoryCreationParams.fromDirectory(this.directory) : super(uri: directory.uri.toString()); /// Constructs an [IOXDirectoryCreationParams] from a [PlatformXDirectoryCreationParams]. - factory IOXDirectoryCreationParams.fromCreationParams( - PlatformXDirectoryCreationParams params, - ) { + factory IOXDirectoryCreationParams.fromCreationParams(PlatformXDirectoryCreationParams params) { return IOXDirectoryCreationParams(uri: params.uri); } @@ -37,8 +34,7 @@ base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { IOXDirectory(super.params) : super.implementation(); @override - late final IOXDirectoryCreationParams params = - super.params is IOXDirectoryCreationParams + late final IOXDirectoryCreationParams params = super.params is IOXDirectoryCreationParams ? super.params as IOXDirectoryCreationParams : IOXDirectoryCreationParams.fromCreationParams(super.params); @@ -56,9 +52,7 @@ base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { await for (final FileSystemEntity entity in directory.list()) { switch (entity) { case final Directory directory: - yield IOXDirectory( - IOXDirectoryCreationParams.fromDirectory(directory), - ); + yield IOXDirectory(IOXDirectoryCreationParams.fromDirectory(directory)); case final File file: yield IOXFile(IOXFileCreationParams.fromFile(file)); } diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index e482bd31df74..5c6bfdbea675 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -14,16 +14,13 @@ import 'package:path/path.dart' as path; @immutable base class IOXFileCreationParams extends PlatformXFileCreationParams { /// Constructs an [IOXFileCreationParams]. - IOXFileCreationParams({required String uri}) - : this.fromFile(File.fromUri(Uri.parse(uri))); + IOXFileCreationParams({required String uri}) : this.fromFile(File.fromUri(Uri.parse(uri))); /// Constructs an [IOXFileCreationParams] from a [File]. IOXFileCreationParams.fromFile(this.file) : super(uri: file.uri.toString()); /// Constructs an [IOXFileCreationParams] from a [PlatformXFileCreationParams]. - factory IOXFileCreationParams.fromCreationParams( - PlatformXFileCreationParams params, - ) { + factory IOXFileCreationParams.fromCreationParams(PlatformXFileCreationParams params) { return IOXFileCreationParams(uri: params.uri); } @@ -37,8 +34,7 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { IOXFile(super.params) : super.implementation(); @override - late final IOXFileCreationParams params = - super.params is IOXFileCreationParams + late final IOXFileCreationParams params = super.params is IOXFileCreationParams ? super.params as IOXFileCreationParams : IOXFileCreationParams.fromCreationParams(super.params); @@ -67,15 +63,13 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { } @override - Stream openRead([int? start, int? end]) => - file.openRead(start, end).cast(); + Stream openRead([int? start, int? end]) => file.openRead(start, end).cast(); @override Future readAsBytes() => file.readAsBytes(); @override - Future readAsString({Encoding encoding = utf8}) => - file.readAsString(encoding: encoding); + Future readAsString({Encoding encoding = utf8}) => file.readAsString(encoding: encoding); @override Future exists() async => file.existsSync(); diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart index cee64ff41677..b4c2636bd0d8 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -9,9 +9,7 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'package:flutter_test/flutter_test.dart'; import 'package:path/path.dart' as path; -final Directory testDirectory = Directory( - path.join(Directory.current.path, 'test'), -); +final Directory testDirectory = Directory(path.join(Directory.current.path, 'test')); void main() { group('IOXFile', () { diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index a57190e5ea3f..07f655b9807e 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -9,9 +9,7 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'package:flutter_test/flutter_test.dart'; import 'package:path/path.dart' as path; -final File testFile = File( - path.join(Directory.current.path, 'test', 'test_file.txt'), -); +final File testFile = File(path.join(Directory.current.path, 'test', 'test_file.txt')); void main() { group('IOXFile', () { @@ -20,60 +18,43 @@ void main() { }); test('lastModified', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); expect(await file.lastModified(), testFile.lastModifiedSync()); }); test('length', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); expect(await file.length(), await testFile.length()); }); test('openRead', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); - - expect( - await file.openRead().toList(), - await testFile.openRead().toList(), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + + expect(await file.openRead().toList(), await testFile.openRead().toList()); }); test('readAsBytes', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); expect(await file.readAsBytes(), await testFile.readAsBytes()); }); test('readAsString', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); expect(await file.readAsString(), await testFile.readAsString()); }); test('exists', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); expect(await file.exists(), testFile.existsSync()); }); test('name', () async { - final file = PlatformXFile( - PlatformXFileCreationParams(uri: testFile.uri.toString()), - ); + final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); expect(await file.name(), 'test_file.txt'); }); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index e0a0e02982e8..78a9093fbfba 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -25,9 +25,7 @@ abstract base class CrossFilePlatform { } /// Creates a new [PlatformXDirectory]. - PlatformXDirectory createPlatformXDirectory( - PlatformXDirectoryCreationParams params, - ) { + PlatformXDirectory createPlatformXDirectory(PlatformXDirectoryCreationParams params) { return _DefaultXDirectory(params); } @@ -131,8 +129,7 @@ final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { /// Implementation of [PlatformScopedStorageXDirectory} that represents a /// directory that does not exist. -final class _DefaultScopedStorageXDirectory - extends PlatformScopedStorageXDirectory { +final class _DefaultScopedStorageXDirectory extends PlatformScopedStorageXDirectory { _DefaultScopedStorageXDirectory(super.params) : super.implementation(); @override diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index afdb85a56633..86c2869025f1 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -40,8 +40,7 @@ import 'platform_cross_entity.dart'; /// } /// ``` @immutable -base class PlatformXDirectoryCreationParams - extends PlatformXEntityCreationParams { +base class PlatformXDirectoryCreationParams extends PlatformXEntityCreationParams { /// Constructs a [PlatformXDirectoryCreationParams]. const PlatformXDirectoryCreationParams({required super.uri}); } @@ -88,13 +87,10 @@ abstract base class PlatformXDirectory extends PlatformXEntity { /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformXDirectory.implementation( - PlatformXDirectoryCreationParams super.params, - ); + PlatformXDirectory.implementation(PlatformXDirectoryCreationParams super.params); @override - PlatformXDirectoryCreationParams get params => - super.params as PlatformXDirectoryCreationParams; + PlatformXDirectoryCreationParams get params => super.params as PlatformXDirectoryCreationParams; /// Lists the sub-directories and files of this Directory. /// diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 8fe7be660a5d..5961dff151c4 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -91,8 +91,7 @@ abstract base class PlatformXFile extends PlatformXEntity { PlatformXFile.implementation(PlatformXFileCreationParams super.params); @override - PlatformXFileCreationParams get params => - super.params as PlatformXFileCreationParams; + PlatformXFileCreationParams get params => super.params as PlatformXFileCreationParams; /// Date and time when the resource was last modified, if the information is /// available. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index c96a27755533..e1f403b65661 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -38,8 +38,7 @@ import '../platform_cross_directory.dart'; /// } /// ``` @immutable -base class PlatformScopedStorageXDirectoryCreationParams - extends PlatformXDirectoryCreationParams { +base class PlatformScopedStorageXDirectoryCreationParams extends PlatformXDirectoryCreationParams { /// Constructs a [PlatformScopedStorageXDirectoryCreationParams]. const PlatformScopedStorageXDirectoryCreationParams({required super.uri}); } @@ -65,16 +64,13 @@ base class PlatformScopedStorageXDirectoryCreationParams /// Future platformMethod(); /// } /// ``` -mixin PlatformScopedStorageXDirectoryExtension - implements PlatformXDirectoryExtension {} +mixin PlatformScopedStorageXDirectoryExtension implements PlatformXDirectoryExtension {} /// A reference to a directory (or folder) on the file system within a device's /// scoped storage. abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { /// Creates a new [PlatformScopedStorageXDirectory] - factory PlatformScopedStorageXDirectory( - PlatformScopedStorageXDirectoryCreationParams params, - ) { + factory PlatformScopedStorageXDirectory(PlatformScopedStorageXDirectoryCreationParams params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' @@ -82,9 +78,7 @@ abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { '`CrossFilePlatform.instance` before use. For unit testing, ' '`CrossFilePlatform.instance` can be set with your own test implementation.', ); - return CrossFilePlatform.instance!.createPlatformScopedStorageXDirectory( - params, - ); + return CrossFilePlatform.instance!.createPlatformScopedStorageXDirectory(params); } /// Used by the platform implementation to create a new diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index 8a7c5d38bd58..a01efac9a3ca 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -38,8 +38,7 @@ import '../platform_cross_file.dart'; /// } /// ``` @immutable -base class PlatformScopedStorageXFileCreationParams - extends PlatformXFileCreationParams { +base class PlatformScopedStorageXFileCreationParams extends PlatformXFileCreationParams { /// Constructs a [PlatformScopedStorageXFileCreationParams]. const PlatformScopedStorageXFileCreationParams({required super.uri}); } @@ -71,9 +70,7 @@ mixin PlatformScopedStorageXFileExtension implements PlatformXFileExtension {} /// scoped storage. abstract base class PlatformScopedStorageXFile extends PlatformXFile { /// Creates a new [PlatformScopedStorageXFile] - factory PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams params, - ) { + factory PlatformScopedStorageXFile(PlatformScopedStorageXFileCreationParams params) { assert( CrossFilePlatform.instance != null, 'A platform implementation for `cross_file` has not been set. Please ' @@ -90,9 +87,8 @@ abstract base class PlatformScopedStorageXFile extends PlatformXFile { /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformScopedStorageXFile.implementation( - PlatformScopedStorageXFileCreationParams super.params, - ) : super.implementation(); + PlatformScopedStorageXFile.implementation(PlatformScopedStorageXFileCreationParams super.params) + : super.implementation(); @override PlatformScopedStorageXFileCreationParams get params => diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index aeab62ccae30..6c6385d7f238 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -14,9 +14,7 @@ void main() { expect( await platform - .createPlatformXFile( - const PlatformXFileCreationParams(uri: 'test'), - ) + .createPlatformXFile(const PlatformXFileCreationParams(uri: 'test')) .exists(), false, ); @@ -30,9 +28,7 @@ void main() { expect( await platform - .createPlatformXDirectory( - const PlatformXDirectoryCreationParams(uri: 'test'), - ) + .createPlatformXDirectory(const PlatformXDirectoryCreationParams(uri: 'test')) .exists(), false, ); @@ -63,9 +59,7 @@ void main() { expect( await platform .createPlatformScopedStorageXDirectory( - const PlatformScopedStorageXDirectoryCreationParams( - uri: 'test', - ), + const PlatformScopedStorageXDirectoryCreationParams(uri: 'test'), ) .exists(), false, diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index 1140ca51d051..4fd5f49b8b5d 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -72,10 +72,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Open a File'), - backgroundColor: Colors.blue, - ), + appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -106,11 +103,7 @@ class FileOpenScreen extends StatelessWidget { /// Widget that displays a text file in a dialog. class TextDisplay extends StatelessWidget { /// Default Constructor. - const TextDisplay({ - super.key, - required this.filename, - required this.fileContents, - }); + const TextDisplay({super.key, required this.filename, required this.fileContents}); /// The name of the file. final String filename; @@ -122,14 +115,9 @@ class TextDisplay extends StatelessWidget { Widget build(BuildContext context) { return AlertDialog( title: Text(filename), - content: Scrollbar( - child: SingleChildScrollView(child: Text(fileContents)), - ), + content: Scrollbar(child: SingleChildScrollView(child: Text(fileContents))), actions: [ - TextButton( - child: const Text('Close'), - onPressed: () => Navigator.pop(context), - ), + TextButton(child: const Text('Close'), onPressed: () => Navigator.pop(context)), ], ); } diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart index cfbac22cfe1f..97b03b08e0ed 100644 --- a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -15,8 +15,7 @@ base class CrossFileWeb extends CrossFilePlatform { } /// Whether the current implementation of `cross_file` is [CrossFileWeb]. - static bool isCurrentImplementation() => - CrossFilePlatform.instance.runtimeType == CrossFileWeb; + static bool isCurrentImplementation() => CrossFilePlatform.instance.runtimeType == CrossFileWeb; @override WebScopedStorageXFile createPlatformScopedStorageXFile( diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index 925afd9f858c..eb9573003b1a 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -41,11 +41,7 @@ Element ensureInitialized(String id) { /// the file to whatever they want before it's actually saved. /// /// Maybe some day: https://developer.mozilla.org/en-US/docs/Web/API/Window/showSaveFilePicker -void downloadObjectUrl( - String objectUrl, - String? name, { - XFileTestOverrides? testOverrides, -}) { +void downloadObjectUrl(String objectUrl, String? name, {XFileTestOverrides? testOverrides}) { // Create a DOM container where the anchor can be injected. final Element target = ensureInitialized('__x_file_dom_element'); @@ -70,8 +66,7 @@ Future blobToBytes(Blob blob) async { reader.readAsArrayBuffer(blob); await reader.onLoadEnd.first; - final Uint8List? result = (reader.result as JSArrayBuffer?)?.toDart - .asUint8List(); + final Uint8List? result = (reader.result as JSArrayBuffer?)?.toDart.asUint8List(); if (result == null) { throw Exception('Cannot read bytes from Blob. Is it still available?'); } @@ -81,10 +76,7 @@ Future blobToBytes(Blob blob) async { /// Converts a bunch of [bytes] into a [Blob] and an optional [mimeType]. Blob bytesToBlob(Uint8List bytes, String? mimeType) { - return Blob( - [bytes.toJS].toJS, - BlobPropertyBag(type: mimeType ?? ''), - ); + return Blob([bytes.toJS].toJS, BlobPropertyBag(type: mimeType ?? '')); } /// Retrieves a [Blob] by its [objectUrl]. diff --git a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart index 36443d6edb64..cdb35dd6d7b8 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart @@ -14,22 +14,15 @@ import 'web_helpers.dart'; /// Base implementation of [PlatformScopedStorageXFileCreationParams] for web. @immutable -sealed class WebScopedStorageXFileCreationParams - extends PlatformScopedStorageXFileCreationParams { +sealed class WebScopedStorageXFileCreationParams extends PlatformScopedStorageXFileCreationParams { /// Constructs a [WebScopedStorageXFileCreationParams]. - const WebScopedStorageXFileCreationParams({ - required super.uri, - this.testOverrides, - }); + const WebScopedStorageXFileCreationParams({required super.uri, this.testOverrides}); /// Constructs a [WebScopedStorageXFileCreationParams] with an object url. factory WebScopedStorageXFileCreationParams.fromObjectUrl({ required String objectUrl, @visibleForTesting XFileTestOverrides? testOverrides, - }) => UrlWebScopedStorageXFileCreationParams( - objectUrl: objectUrl, - testOverrides: testOverrides, - ); + }) => UrlWebScopedStorageXFileCreationParams(objectUrl: objectUrl, testOverrides: testOverrides); /// Constructs a [WebScopedStorageXFileCreationParams] with a [Blob]. /// @@ -55,8 +48,7 @@ sealed class WebScopedStorageXFileCreationParams /// Implementation of [WebScopedStorageXFileCreationParams] with an object url. @immutable -base class UrlWebScopedStorageXFileCreationParams - extends WebScopedStorageXFileCreationParams { +base class UrlWebScopedStorageXFileCreationParams extends WebScopedStorageXFileCreationParams { /// Constructs a [UrlWebScopedStorageXFileCreationParams]. const UrlWebScopedStorageXFileCreationParams({ required String objectUrl, @@ -66,8 +58,7 @@ base class UrlWebScopedStorageXFileCreationParams /// Implementation of [WebScopedStorageXFileCreationParams] with a [Blob]. @immutable -base class BlobWebScopedStorageXFileCreationParams - extends WebScopedStorageXFileCreationParams { +base class BlobWebScopedStorageXFileCreationParams extends WebScopedStorageXFileCreationParams { /// Constructs a [BlobWebScopedStorageXFileCreationParams]. BlobWebScopedStorageXFileCreationParams( this.blob, { @@ -183,8 +174,7 @@ base class WebScopedStorageXFile extends PlatformScopedStorageXFile } /// Provides platform specific features for [WebScopedStorageXFile]. -mixin WebScopedStorageXFileExtension - implements PlatformScopedStorageXFileExtension { +mixin WebScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension { /// The raw data represented by a [WebScopedStorageXFile]. Future getBlob(); diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index 44e40595b72f..10a032d1ab01 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -17,13 +17,8 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:web/web.dart' as html; const String testFileStringContents = 'Hello, world! I ❤ ñ! 空手'; -final Uint8List testFileBytes = Uint8List.fromList( - utf8.encode(testFileStringContents), -); -final html.File testFile = html.File( - [testFileBytes.toJS].toJS, - 'hello.txt', -); +final Uint8List testFileBytes = Uint8List.fromList(utf8.encode(testFileStringContents)); +final html.File testFile = html.File([testFileBytes.toJS].toJS, 'hello.txt'); final String testFileUrl = html.URL.createObjectURL(testFile as JSObject); void main() { @@ -160,9 +155,7 @@ void main() { await file.download(''); - final html.Element? container = html.document.querySelector( - '#$crossFileDomElementId', - ); + final html.Element? container = html.document.querySelector('#$crossFileDomElementId'); expect(container, isNotNull); }); @@ -174,9 +167,7 @@ void main() { await file.download('path'); - final html.Element container = html.document.querySelector( - '#$crossFileDomElementId', - )!; + final html.Element container = html.document.querySelector('#$crossFileDomElementId')!; late html.HTMLAnchorElement element; for (var i = 0; i < container.childNodes.length; i++) { @@ -193,18 +184,12 @@ void main() { }); test('anchor element is clicked', () async { - final mockAnchor = - html.document.createElement('a') as html.HTMLAnchorElement; + final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; - final testOverrides = XFileTestOverrides( - createAnchorElement: (_, __) => mockAnchor, - ); + final testOverrides = XFileTestOverrides(createAnchorElement: (_, __) => mockAnchor); final file = WebScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob( - testFile, - testOverrides: testOverrides, - ), + WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), ); var clicked = false; From 4dd921bbe9f7c4d93f4880ddf9f77a79a850adde Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:03:38 -0400 Subject: [PATCH 309/398] excerpts and analyze --- packages/cross_file/cross_file/README.md | 4 ++-- .../cross_file/cross_file/example/lib/readme_excerpts.dart | 4 ++-- packages/cross_file/cross_file_io/lib/src/io_cross_file.dart | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index d696df3364cc..08900b648ad9 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -87,13 +87,13 @@ if (CrossFileWeb.isCurrentImplementation()) { } await file - .maybeGetExtension() + .maybeGetExtension() ?.startAccessingSecurityScopedResource(); debugPrint(await file.readAsString()); await file - .maybeGetExtension() + .maybeGetExtension() ?.stopAccessingSecurityScopedResource(); ``` diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index a558486ca627..9d68935cd960 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -46,13 +46,13 @@ Future accessPlatformFeatures() async { } await file - .maybeGetExtension() + .maybeGetExtension() ?.startAccessingSecurityScopedResource(); debugPrint(await file.readAsString()); await file - .maybeGetExtension() + .maybeGetExtension() ?.stopAccessingSecurityScopedResource(); // #enddocregion platform_features diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 5c6bfdbea675..9d844e474e8c 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -56,7 +56,7 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { @override Future length() async { try { - return file.length(); + return await file.length(); } on FileSystemException { return null; } From b63030a32e240ddbaedec8d90099d3a6e1eec976 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:17:40 -0400 Subject: [PATCH 310/398] analyze errors --- packages/cross_file/cross_file_darwin/tool/ffigen.dart | 1 - .../cross_file/cross_file_web/test/web_cross_file_test.dart | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 0b4bb052616b..eac2c2e05f0c 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -24,7 +24,6 @@ void main() { objectiveC: ObjectiveC( interfaces: Interfaces( include: (Declaration declaration) { - print('Apple: ${declaration.originalName}'); return { 'NSFileManager', 'NSObject', diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index 10a032d1ab01..18af63c2f3d8 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -186,7 +186,7 @@ void main() { test('anchor element is clicked', () async { final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; - final testOverrides = XFileTestOverrides(createAnchorElement: (_, __) => mockAnchor); + final testOverrides = XFileTestOverrides(createAnchorElement: (_, _) => mockAnchor); final file = WebScopedStorageXFile( WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), From 6613d68aadc38fe2fefd90d44bd5c7f609aaadda Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:43:31 -0400 Subject: [PATCH 311/398] license --- .../Sources/cross_file_darwin_objc/ffi_bindings.g.m | 4 ++++ .../cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart | 3 +++ packages/cross_file/cross_file_darwin/tool/ffigen.dart | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index 3d5f3bb2782b..0950e8b82720 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -1,3 +1,7 @@ +/// Copyright 2013 The Flutter Authors +/// Use of this source code is governed by a BSD-style license that can be +/// found in the LICENSE file. + #import #import #import diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 935780ddbe11..25c940a76bf4 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -1,3 +1,6 @@ +/// Copyright 2013 The Flutter Authors +/// Use of this source code is governed by a BSD-style license that can be +/// found in the LICENSE file. // AUTO GENERATED FILE, DO NOT EDIT. // // Generated by `package:ffigen`. diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index eac2c2e05f0c..04d0c4f79c4e 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -11,6 +11,10 @@ void main() { FfiGenerator( output: Output( dartFile: packageRoot.resolve('lib/src/ffi_bindings.g.dart'), + preamble: + '/// Copyright 2013 The Flutter Authors\n' + '/// Use of this source code is governed by a BSD-style license that can be\n' + '/// found in the LICENSE file.', objectiveCFile: packageRoot.resolve( 'darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m', ), From 6a683623f388c950b01f8f23a2969a2c9c28ca03 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:58:04 -0400 Subject: [PATCH 312/398] use --platform --- packages/cross_file/cross_file_web/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md index a5063b9a37aa..7348da8be6da 100644 --- a/packages/cross_file/cross_file_web/README.md +++ b/packages/cross_file/cross_file_web/README.md @@ -30,7 +30,7 @@ its size is known beforehand), so that case can be handled programmatically. ### Tests -Tests for the web platform can be run with `flutter test -d chrome`. +Tests for the web platform can be run with `flutter test --platform chrome`. [1]: https://pub.dev/packages/cross_file [2]: https://flutter.dev/to/endorsed-federated-plugin From aa6e666f352df128b9f5adedeca423bb771ae851 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:35:36 -0400 Subject: [PATCH 313/398] dash --- packages/cross_file/cross_file/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file/CHANGELOG.md b/packages/cross_file/cross_file/CHANGELOG.md index 9091fdcc51fb..83619ea75579 100644 --- a/packages/cross_file/cross_file/CHANGELOG.md +++ b/packages/cross_file/cross_file/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.4.0 -* Updates `cross_file` to a package separated federated plugin. +* Updates `cross_file` to a package-separated federated plugin. * Updates minimum supported SDK version to Flutter 3.38/Dart 3.10. ## 0.3.5+2 From 5c26447bd47e48f163b34e3336c9fd32b7788d96 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:49:41 -0400 Subject: [PATCH 314/398] add darwin dep --- .../cross_file/cross_file_darwin/example/lib/main.dart | 7 ++++++- packages/cross_file/cross_file_darwin/example/pubspec.yaml | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 7c272a16c3ed..e4b89c24d838 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cross_file_darwin/cross_file_darwin.dart'; import 'package:file_selector/file_selector.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -29,7 +30,11 @@ class FileOpenScreen extends StatelessWidget { context: context, builder: (BuildContext context) => TextDisplay(filename: filename, fileContents: fileContents), - ); + ).then((_) { + file + .getExtension() + .stopAccessingSecurityScopedResource(); + }); } case _: debugPrint('File Uri: ${file.uri}'); diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index cfcec044e0d3..6ef0db20ba87 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -7,6 +7,13 @@ environment: flutter: ">=3.38.0" dependencies: + cross_file_darwin: + # When depending on this package from a real application you should use: + # cross_file_darwin: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ cupertino_icons: ^1.0.8 file_selector: git: From 6c5f5979d973538231a9a57217fec0795af1c436 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 14:51:33 -0400 Subject: [PATCH 315/398] remove configs --- .../example/macos/Runner/Configs/Debug.xcconfig | 1 - .../example/macos/Runner/Configs/Release.xcconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig index 36b0fd9464f4..786963738d3e 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig @@ -1,2 +1 @@ -#include "../../Flutter/Flutter-Debug.xcconfig" #include "Warnings.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig index dff4f49561c8..786963738d3e 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig @@ -1,2 +1 @@ -#include "../../Flutter/Flutter-Release.xcconfig" #include "Warnings.xcconfig" From eba22d5a79314be9f097911cd659aa140eea5f57 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 17 Jun 2026 15:03:44 -0400 Subject: [PATCH 316/398] fix license --- .../Sources/cross_file_darwin_objc/ffi_bindings.g.m | 6 +++--- .../cross_file_darwin/lib/src/ffi_bindings.g.dart | 6 +++--- packages/cross_file/cross_file_darwin/tool/ffigen.dart | 6 +++--- packages/cross_file/cross_file_web/lib/src/web_helpers.dart | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index 0950e8b82720..fc7d39ee327a 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -1,6 +1,6 @@ -/// Copyright 2013 The Flutter Authors -/// Use of this source code is governed by a BSD-style license that can be -/// found in the LICENSE file. +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #import #import diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 25c940a76bf4..4aa8896313dd 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -1,6 +1,6 @@ -/// Copyright 2013 The Flutter Authors -/// Use of this source code is governed by a BSD-style license that can be -/// found in the LICENSE file. +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. // AUTO GENERATED FILE, DO NOT EDIT. // // Generated by `package:ffigen`. diff --git a/packages/cross_file/cross_file_darwin/tool/ffigen.dart b/packages/cross_file/cross_file_darwin/tool/ffigen.dart index 04d0c4f79c4e..70fe8f50543d 100644 --- a/packages/cross_file/cross_file_darwin/tool/ffigen.dart +++ b/packages/cross_file/cross_file_darwin/tool/ffigen.dart @@ -12,9 +12,9 @@ void main() { output: Output( dartFile: packageRoot.resolve('lib/src/ffi_bindings.g.dart'), preamble: - '/// Copyright 2013 The Flutter Authors\n' - '/// Use of this source code is governed by a BSD-style license that can be\n' - '/// found in the LICENSE file.', + '// Copyright 2013 The Flutter Authors\n' + '// Use of this source code is governed by a BSD-style license that can be\n' + '// found in the LICENSE file.', objectiveCFile: packageRoot.resolve( 'darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m', ), diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index eb9573003b1a..f9af59765ced 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -83,7 +83,7 @@ Blob bytesToBlob(Uint8List bytes, String? mimeType) { Future fetchBlob(String objectUrl) async { try { final Response response = await window.fetch(objectUrl.toJS).toDart; - return response.blob().toDart; + return await response.blob().toDart; } catch (e) { throw Exception('Could not fetch Blob by URL: $objectUrl'); } From 43b9fb02e7df0a9d7b809ad3967df59d5bff6779 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 18 Jun 2026 12:51:52 -0400 Subject: [PATCH 317/398] fix web test requiring SIGKILL --- .../test/web_cross_file_test.dart | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart index 18af63c2f3d8..4647b5b81acb 100644 --- a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_cross_file_test.dart @@ -149,11 +149,14 @@ void main() { group('XFile download', () { test('creates a DOM container', () async { + final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; + final testOverrides = XFileTestOverrides(createAnchorElement: (_, _) => mockAnchor); + final file = WebScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), + WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), ); - await file.download(''); + await file.download(); final html.Element? container = html.document.querySelector('#$crossFileDomElementId'); @@ -161,26 +164,36 @@ void main() { }); test('create anchor element', () async { + final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; + late final String setHref; + late final String? setDownload; + final testOverrides = XFileTestOverrides( + createAnchorElement: (String href, String? suggestedName) { + setHref = href; + setDownload = suggestedName; + return mockAnchor; + }, + ); + final file = WebScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), + WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), ); await file.download('path'); final html.Element container = html.document.querySelector('#$crossFileDomElementId')!; - late html.HTMLAnchorElement element; + // Find anchor element. + late final html.HTMLAnchorElement element; for (var i = 0; i < container.childNodes.length; i++) { - final html.Element test = container.children.item(i)!; - if (test.tagName == 'A') { - element = test as html.HTMLAnchorElement; - break; - } + element = container.children.item(i)! as html.HTMLAnchorElement; } - // if element is not found, the `firstWhere` call will throw StateError. - expect(element.href, file.params.uri); - expect(element.download, 'path'); + // If element is not found, the `firstWhere` call will throw StateError. + expect(element, mockAnchor); + expect(element.tagName, 'A'); + expect(setHref, file.params.uri); + expect(setDownload, 'path'); }); test('anchor element is clicked', () async { From 49ae6347d0412a6bb5cb2f5c88ff81e8a7eef074 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 15:40:09 -0400 Subject: [PATCH 318/398] update to use ffigen --- .../Tests/AssetResourceReaderTests.swift | 36 - .../darwin/Tests/CrossFileDarwinTests.swift | 22 + .../darwin/Tests/TestProxyAPIRegistrar.swift | 56 -- .../AssetResourceReader.swift | 60 -- .../CrossFileDarwinApis.g.swift | 768 ------------------ .../CrossFileDarwinPlugin.swift | 23 - .../cross_file_darwin/ProxyAPIRegistrar.swift | 55 -- .../AssetResourceReaderAPIDelegate.swift | 63 -- .../ios/Runner.xcodeproj/project.pbxproj | 12 +- .../macos/Runner.xcodeproj/project.pbxproj | 12 +- .../RunnerTests/CrossFileDarwinTests.swift | 22 + .../lib/src/cross_file_darwin_apis.g.dart | 657 --------------- .../src/darwin_scoped_storage_cross_file.dart | 46 +- .../cross_file_darwin/pigeons/copyright.txt | 3 - .../pigeons/cross_file_darwin_apis.dart | 46 -- .../cross_file/cross_file_darwin/pubspec.yaml | 3 - ...darwin_scoped_storage_cross_file_test.dart | 92 --- ..._scoped_storage_cross_file_test.mocks.dart | 87 -- 18 files changed, 80 insertions(+), 1983 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift delete mode 100644 packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift create mode 100644 packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift delete mode 100644 packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart delete mode 100644 packages/cross_file/cross_file_darwin/pigeons/copyright.txt delete mode 100644 packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart delete mode 100644 packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift deleted file mode 100644 index 2749671856be..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/AssetResourceReaderTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Testing - -@testable import cross_file_darwin - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -struct AssetResourceReaderTests { - func createTempTestFile() throws -> URL { - let fileManager = FileManager.default - let tempDirectory = fileManager.temporaryDirectory - let fileName = UUID().uuidString + ".txt" - let fileURL = tempDirectory.appendingPathComponent(fileName) - - try "Hello, World!".write(to: fileURL, atomically: true, encoding: .utf8) - - return fileURL - } - - @Test func pigeonDefaultConstructor() throws { - let registrar = TestProxyApiRegistrar() - let api = registrar.apiDelegate.pigeonApiAssetResourceReader(registrar) - - let instance = try? api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api) - #expect(instance != nil) - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift new file mode 100644 index 000000000000..a222c2c29a14 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Testing + +@testable import cross_file_darwin + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +// Placeholder for adding tests. +struct CrossFileDarwinTests { + @Test func placeHoldertTest() throws { + #expect(true == true) + } +} diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift deleted file mode 100644 index 91fb17a68399..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/TestProxyAPIRegistrar.swift +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import XCTest - -@testable import cross_file_darwin - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -class TestProxyApiRegistrar: ProxyAPIRegistrar { - init() { - super.init( - binaryMessenger: TestBinaryMessenger()) - } - - override func dispatchOnMainThread( - execute work: @escaping (@escaping (String, PigeonError) -> Void) -> Void - ) { - work { _, _ in } - } -} - -class TestBundle: Bundle, @unchecked Sendable { - override func url(forResource name: String?, withExtension ext: String?) -> URL? { - return URL(string: "assets/www/index.html")! - } -} - -class TestBinaryMessenger: NSObject, FlutterBinaryMessenger { - func send(onChannel channel: String, message: Data?) { - - } - - func send( - onChannel channel: String, message: Data?, binaryReply callback: FlutterBinaryReply? = nil - ) { - - } - - func setMessageHandlerOnChannel( - _ channel: String, binaryMessageHandler handler: FlutterBinaryMessageHandler? = nil - ) -> FlutterBinaryMessengerConnection { - return 0 - } - - func cleanUpConnection(_ connection: FlutterBinaryMessengerConnection) { - - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift deleted file mode 100644 index 7b854e856e7f..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Photos - -/// Class for handling an instance of asynchronously reading bytes from -/// `PHAssetResourceManager.requestDataForAssetResource`. -class AssetResourceReader { - /// Handles the bytes read. - var delegate: AssetResourceReaderDelegate? - - /// Begin reading bytes from PHAssetResource with `localIdentifier`. - func startRead(localIdentifier: String) -> Bool { - let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) - if let asset = assets.firstObject { - let resources = PHAssetResource.assetResources(for: asset) - if let resource = resources.first { - let resourceManager = PHAssetResourceManager.default() - - let options = PHAssetResourceRequestOptions() - options.isNetworkAccessAllowed = true - - resourceManager.requestData(for: resource, options: options) { data in - DispatchQueue.main.async { - self.delegate?.onDataReceived(reader: self, bytes: data) - } - } completionHandler: { error in - DispatchQueue.main.async { - self.delegate?.onCompletion(reader: self, error: error?.localizedDescription) - } - } - - return true - } - } - - return false - } -} - -/// Handles bytes read from calling `AssetResourceReader.startRead`. -protocol AssetResourceReaderDelegate { - /// Provides the requested data. - /// - /// Called multiple times until all bytes are received. - /// - /// Corresponds to the `dataReceivedHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived(reader: AssetResourceReader, bytes: Data) - - /// Start reading bytes from the asset with the given identifier. - /// - /// Returns false if the resource for the identifier could not be accessed or - /// found. Returns true if the resource can be successfully accessed. - /// - /// Bytes are passed to `onDataReceived` and the request is completed when - /// `onCompletion` is called. - func onCompletion(reader: AssetResourceReader, error: String?) -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift deleted file mode 100644 index 232759a2f8ad..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ /dev/null @@ -1,768 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.3.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -/// Error class for passing custom error details to Dart side. -final class PigeonError: Error { - let code: String - let message: String? - let details: Sendable? - - init(code: String, message: String?, details: Sendable?) { - self.code = code - self.message = message - self.details = details - } - - var localizedDescription: String { - return - "PigeonError(code: \(code), message: \(message ?? ""), details: \(details ?? "")" - } -} - -private func wrapResult(_ result: Any?) -> [Any?] { - return [result] -} - -private func wrapError(_ error: Any) -> [Any?] { - if let pigeonError = error as? PigeonError { - return [ - pigeonError.code, - pigeonError.message, - pigeonError.details, - ] - } - if let flutterError = error as? FlutterError { - return [ - flutterError.code, - flutterError.message, - flutterError.details, - ] - } - return [ - "\(error)", - "\(Swift.type(of: error))", - "Stacktrace: \(Thread.callStackSymbols)", - ] -} - -private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError( - code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", - details: "") -} - -private func isNullish(_ value: Any?) -> Bool { - return value is NSNull || value == nil -} - -private func nilOrValue(_ value: Any?) -> T? { - if value is NSNull { return nil } - return value as! T? -} - -/// Handles the callback when an object is deallocated. -protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { - /// Invoked when the strong reference of an object is deallocated in an `InstanceManager`. - func onDeinit(identifier: Int64) -} - -// Attaches to an object to receive a callback when the object is deallocated. -internal final class CrossFileDarwinApisPigeonInternalFinalizer { - internal static let associatedObjectKey = malloc(1)! - - private let identifier: Int64 - // Reference to the delegate is weak because the callback should be ignored if the - // `InstanceManager` is deallocated. - internal weak var delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate? - - private init(identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { - self.identifier = identifier - self.delegate = delegate - } - - internal static func attach( - to instance: AnyObject, identifier: Int64, - delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate - ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( - identifier: identifier, delegate: delegate) - objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) - } - - static func detach(from instance: AnyObject) { - let finalizer = - objc_getAssociatedObject(instance, associatedObjectKey) - as? CrossFileDarwinApisPigeonInternalFinalizer - if let finalizer = finalizer { - finalizer.delegate = nil - objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) - } - } - - deinit { - delegate?.onDeinit(identifier: identifier) - } -} - -/// Maintains instances used to communicate with the corresponding objects in Dart. -/// -/// Objects stored in this container are represented by an object in Dart that is also stored in -/// an InstanceManager with the same identifier. -/// -/// When an instance is added with an identifier, either can be used to retrieve the other. -/// -/// Added instances are added as a weak reference and a strong reference. When the strong -/// reference is removed and the weak reference is deallocated,`CrossFileDarwinApisPigeonInternalFinalizerDelegate.onDeinit` -/// is called with the instance's identifier. However, if the strong reference is removed and then the identifier is -/// retrieved with the intention to pass the identifier to Dart (e.g. by calling `identifierWithStrongReference`), -/// the strong reference to the instance is re-added. The strong reference will then need to be removed manually -/// again. -/// -/// Accessing and inserting to an InstanceManager is thread safe. -final class CrossFileDarwinApisPigeonInstanceManager { - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously from Dart. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - private static let minHostCreatedIdentifier: Int64 = 65536 - - private let lockQueue = DispatchQueue(label: "CrossFileDarwinApisPigeonInstanceManager") - private let identifiers: NSMapTable = NSMapTable( - keyOptions: [.weakMemory, .objectPointerPersonality], valueOptions: .strongMemory) - private let weakInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.weakMemory, .objectPointerPersonality]) - private let strongInstances: NSMapTable = NSMapTable( - keyOptions: .strongMemory, valueOptions: [.strongMemory, .objectPointerPersonality]) - private let finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate - private var nextIdentifier: Int64 = minHostCreatedIdentifier - - public init(finalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate) { - self.finalizerDelegate = finalizerDelegate - } - - /// Adds a new instance that was instantiated from Dart. - /// - /// The same instance can be added multiple times, but each identifier must be unique. This allows - /// two objects that are equivalent (e.g. conforms to `Equatable`) to both be added. - /// - /// - Parameters: - /// - instance: the instance to be stored - /// - identifier: the identifier to be paired with instance. This value must be >= 0 and unique - func addDartCreatedInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - lockQueue.async { - self.addInstance(instance, withIdentifier: identifier) - } - } - - /// Adds a new instance that was instantiated from the host platform. - /// - /// - Parameters: - /// - instance: the instance to be stored. This must be unique to all other added instances. - /// - Returns: the unique identifier (>= 0) stored with instance - func addHostCreatedInstance(_ instance: AnyObject) -> Int64 { - assert(!containsInstance(instance), "Instance of \(instance) has already been added.") - var identifier: Int64 = -1 - lockQueue.sync { - identifier = nextIdentifier - nextIdentifier += 1 - self.addInstance(instance, withIdentifier: identifier) - } - return identifier - } - - /// Removes `instanceIdentifier` and its associated strongly referenced instance, if present, from the manager. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier paired to an instance. - /// - Returns: removed instance if the manager contains the given identifier, otherwise `nil` if - /// the manager doesn't contain the value - func removeInstance(withIdentifier instanceIdentifier: Int64) throws -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = strongInstances.object(forKey: NSNumber(value: instanceIdentifier)) - strongInstances.removeObject(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - /// Retrieves the instance associated with identifier. - /// - /// - Parameters: - /// - instanceIdentifier: the identifier associated with an instance - /// - Returns: the instance associated with `instanceIdentifier` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func instance(forIdentifier instanceIdentifier: Int64) -> T? { - var instance: AnyObject? = nil - lockQueue.sync { - instance = weakInstances.object(forKey: NSNumber(value: instanceIdentifier)) - } - return instance as? T - } - - private func addInstance(_ instance: AnyObject, withIdentifier identifier: Int64) { - assert(identifier >= 0) - assert( - weakInstances.object(forKey: identifier as NSNumber) == nil, - "Identifier has already been added: \(identifier)") - identifiers.setObject(NSNumber(value: identifier), forKey: instance) - weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) - strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach( - to: instance, identifier: identifier, delegate: finalizerDelegate) - } - - /// Retrieves the identifier paired with an instance. - /// - /// If the manager contains a strong reference to `instance`, it will return the identifier - /// associated with `instance`. If the manager contains only a weak reference to `instance`, a new - /// strong reference to `instance` will be added and will need to be removed again with `removeInstance`. - /// - /// If this method returns a nonnull identifier, this method also expects the Dart - /// `CrossFileDarwinApisPigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the - /// identifier is associated with. - /// - /// - Parameters: - /// - instance: an instance that may be stored in the manager - /// - Returns: the identifier associated with `instance` if the manager contains the value, otherwise - /// `nil` if the manager doesn't contain the value - func identifierWithStrongReference(forInstance instance: AnyObject) -> Int64? { - var identifier: Int64? = nil - lockQueue.sync { - if let existingIdentifier = identifiers.object(forKey: instance)?.int64Value { - strongInstances.setObject(instance, forKey: NSNumber(value: existingIdentifier)) - identifier = existingIdentifier - } - } - return identifier - } - - /// Whether this manager contains the given `instance`. - /// - /// - Parameters: - /// - instance: the instance whose presence in this manager is to be tested - /// - Returns: whether this manager contains the given `instance` - func containsInstance(_ instance: AnyObject) -> Bool { - var containsInstance = false - lockQueue.sync { - containsInstance = identifiers.object(forKey: instance) != nil - } - return containsInstance - } - - /// Removes all of the instances from this manager. - /// - /// The manager will be empty after this call returns. - func removeAllObjects() throws { - lockQueue.sync { - let weakInstancesEnumerator = weakInstances.objectEnumerator()! - while let instance = weakInstancesEnumerator.nextObject() { - CrossFileDarwinApisPigeonInternalFinalizer.detach(from: instance as AnyObject) - } - identifiers.removeAllObjects() - weakInstances.removeAllObjects() - strongInstances.removeAllObjects() - nextIdentifier = CrossFileDarwinApisPigeonInstanceManager.minHostCreatedIdentifier - } - } - - /// The number of instances stored as a strong reference. - /// - /// For debugging and testing purposes. - internal var strongInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = strongInstances.count - } - return count - } - - /// The number of instances stored as a weak reference. - /// - /// For debugging and testing purposes. NSMapTables that store keys or objects as weak - /// reference will be reclaimed non-deterministically. - internal var weakInstanceCount: Int { - var count: Int = 0 - lockQueue.sync { - count = weakInstances.count - } - return count - } -} - -private class CrossFileDarwinApisPigeonInstanceManagerApi { - /// The codec used for serializing messages. - var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } - - /// Handles sending and receiving messages with Dart. - unowned let binaryMessenger: FlutterBinaryMessenger - - init(binaryMessenger: FlutterBinaryMessenger) { - self.binaryMessenger = binaryMessenger - } - - /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, - instanceManager: CrossFileDarwinApisPigeonInstanceManager? - ) { - let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel( - name: - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", - binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - removeStrongReferenceChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let identifierArg = args[0] as! Int64 - do { - let _: AnyObject? = try instanceManager.removeInstance(withIdentifier: identifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - removeStrongReferenceChannel.setMessageHandler(nil) - } - let clearChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", - binaryMessenger: binaryMessenger, codec: codec) - if let instanceManager = instanceManager { - clearChannel.setMessageHandler { _, reply in - do { - try instanceManager.removeAllObjects() - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - clearChannel.setMessageHandler(nil) - } - } - - /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference( - identifier identifierArg: Int64, completion: @escaping (Result) -> Void - ) { - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([identifierArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } -} -protocol CrossFileDarwinApisPigeonProxyApiDelegate { - /// An implementation of [PigeonApiAssetResourceReader] used to add a new Dart instance of - /// `AssetResourceReader` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) - -> PigeonApiAssetResourceReader -} - -open class CrossFileDarwinApisPigeonProxyApiRegistrar { - let binaryMessenger: FlutterBinaryMessenger - let apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - let instanceManager: CrossFileDarwinApisPigeonInstanceManager - /// Whether APIs should ignore calling to Dart. - public var ignoreCallsToDart = false - private var _codec: FlutterStandardMessageCodec? - var codec: FlutterStandardMessageCodec { - if _codec == nil { - _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: self)) - } - return _codec! - } - - private class InstanceManagerApiFinalizerDelegate: - CrossFileDarwinApisPigeonInternalFinalizerDelegate - { - let api: CrossFileDarwinApisPigeonInstanceManagerApi - - init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { - self.api = api - } - - public func onDeinit(identifier: Int64) { - api.removeStrongReference(identifier: identifier) { - _ in - } - } - } - - init( - binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate - ) { - self.binaryMessenger = binaryMessenger - self.apiDelegate = apiDelegate - self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( - finalizerDelegate: InstanceManagerApiFinalizerDelegate( - CrossFileDarwinApisPigeonInstanceManagerApi(binaryMessenger: binaryMessenger))) - } - - func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiAssetResourceReader.setUpMessageHandlers( - binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) - } - func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( - binaryMessenger: binaryMessenger, instanceManager: nil) - PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - } -} -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: - FlutterStandardReaderWriter -{ - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: - CrossFileDarwinApisPigeonCodecReader - { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func readValue(ofType type: UInt8) -> Any? { - switch type { - case 128: - let identifier = self.readValue() - let instance: AnyObject? = pigeonRegistrar.instanceManager.instance( - forIdentifier: identifier is Int64 ? identifier as! Int64 : Int64(identifier as! Int32)) - if instance == nil { - print("Failed to find instance with identifier: \(identifier!)") - } - return instance - default: - return super.readValue(ofType: type) - } - } - } - - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: - CrossFileDarwinApisPigeonCodecWriter - { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - - init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - super.init(data: data) - } - - override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] - || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String - { - super.writeValue(value) - return - } - - if let instance = value as? AssetResourceReader { - pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReader(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference( - forInstance: instance as AnyObject)!) - return - } - - if let instance = value as AnyObject?, - pigeonRegistrar.instanceManager.containsInstance(instance) - { - super.writeByte(128) - super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance)!) - } else { - print("Unsupported value: \(value) of \(type(of: value))") - assert(false, "Unsupported value for CrossFileDarwinApisPigeonInternalProxyApiCodecWriter") - } - - } - } - - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { - self.pigeonRegistrar = pigeonRegistrar - } - - override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( - data: data, pigeonRegistrar: pigeonRegistrar) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( - data: data, pigeonRegistrar: pigeonRegistrar) - } -} - -private class CrossFileDarwinApisPigeonCodecReader: FlutterStandardReader { -} - -private class CrossFileDarwinApisPigeonCodecWriter: FlutterStandardWriter { -} - -private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderWriter { - override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonCodecReader(data: data) - } - - override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonCodecWriter(data: data) - } -} - -class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec( - readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) -} - -protocol PigeonApiDelegateAssetResourceReader { - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws - -> AssetResourceReader - /// Start reading bytes from the asset with the given identifier. - /// - /// Returns false if the resource for the identifier could not be accessed or - /// found. Returns true if the resource can be successfully accessed. - /// - /// Bytes are passed to `onDataReceived` and the request is completed when - /// `onCompletion` is called. - func startRead( - pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, - localIdentifier: String - ) throws -> Bool -} - -protocol PigeonApiProtocolAssetResourceReader { - /// Provides the requested data. - /// - /// Called multiple times until all bytes are received. - /// - /// Corresponds to the `dataReceivedHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived( - pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, - completion: @escaping (Result) -> Void) - /// Indicates the request for data has completed. - /// - /// Called once after the request has been fulfilled or has failed. - /// - /// Corresponds to the `completionHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - func onCompletion( - pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, - completion: @escaping (Result) -> Void) -} - -final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { - unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - let pigeonDelegate: PigeonApiDelegateAssetResourceReader - init( - pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, - delegate: PigeonApiDelegateAssetResourceReader - ) { - self.pigeonRegistrar = pigeonRegistrar - self.pigeonDelegate = delegate - } - static func setUpMessageHandlers( - binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader? - ) { - let codec: FlutterStandardMessageCodec = - api != nil - ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( - pigeonRegistrar: api!.pigeonRegistrar)) - : FlutterStandardMessageCodec.sharedInstance() - let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - pigeonDefaultConstructorChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonIdentifierArg = args[0] as! Int64 - do { - api.pigeonRegistrar.instanceManager.addDartCreatedInstance( - try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), - withIdentifier: pigeonIdentifierArg) - reply(wrapResult(nil)) - } catch { - reply(wrapError(error)) - } - } - } else { - pigeonDefaultConstructorChannel.setMessageHandler(nil) - } - let startReadChannel = FlutterBasicMessageChannel( - name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead", - binaryMessenger: binaryMessenger, codec: codec) - if let api = api { - startReadChannel.setMessageHandler { message, reply in - let args = message as! [Any?] - let pigeonInstanceArg = args[0] as! AssetResourceReader - let localIdentifierArg = args[1] as! String - do { - let result = try api.pigeonDelegate.startRead( - pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) - reply(wrapResult(result)) - } catch { - reply(wrapError(error)) - } - } - } else { - startReadChannel.setMessageHandler(nil) - } - } - - ///Creates a Dart instance of AssetResourceReader and attaches it to [pigeonInstance]. - func pigeonNewInstance( - pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { - completion(.success(())) - } else { - completion( - .failure( - PigeonError( - code: "new-instance-error", - message: - "Error: Attempting to create a new Dart instance of AssetResourceReader, but the class has a nonnull callback method.", - details: ""))) - } - } - /// Provides the requested data. - /// - /// Called multiple times until all bytes are received. - /// - /// Corresponds to the `dataReceivedHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived( - pigeonInstance pigeonInstanceArg: AssetResourceReader, bytes bytesArg: FlutterStandardTypedData, - completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { - completion( - .failure( - PigeonError( - code: "missing-instance-error", - message: - "Callback to `AssetResourceReader.onDataReceived` failed because native instance was not in the instance manager.", - details: ""))) - return - } - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonInstanceArg, bytesArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - - /// Indicates the request for data has completed. - /// - /// Called once after the request has been fulfilled or has failed. - /// - /// Corresponds to the `completionHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - func onCompletion( - pigeonInstance pigeonInstanceArg: AssetResourceReader, error errorArg: String?, - completion: @escaping (Result) -> Void - ) { - if pigeonRegistrar.ignoreCallsToDart { - completion( - .failure( - PigeonError( - code: "ignore-calls-error", - message: "Calls to Dart are being ignored.", details: ""))) - return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { - completion( - .failure( - PigeonError( - code: "missing-instance-error", - message: - "Callback to `AssetResourceReader.onCompletion` failed because native instance was not in the instance manager.", - details: ""))) - return - } - let binaryMessenger = pigeonRegistrar.binaryMessenger - let codec = pigeonRegistrar.codec - let channelName: String = - "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion" - let channel = FlutterBasicMessageChannel( - name: channelName, binaryMessenger: binaryMessenger, codec: codec) - channel.sendMessage([pigeonInstanceArg, errorArg] as [Any?]) { response in - guard let listResponse = response as? [Any?] else { - completion(.failure(createConnectionError(withChannelName: channelName))) - return - } - if listResponse.count > 1 { - let code: String = listResponse[0] as! String - let message: String? = nilOrValue(listResponse[1]) - let details: String? = nilOrValue(listResponse[2]) - completion(.failure(PigeonError(code: code, message: message, details: details))) - } else { - completion(.success(())) - } - } - } - -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift index 429910764cc1..9af279da47ca 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift @@ -11,30 +11,7 @@ #endif public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { - var proxyApiRegistrar: ProxyAPIRegistrar? - - init(binaryMessenger: FlutterBinaryMessenger) { - proxyApiRegistrar = ProxyAPIRegistrar( - binaryMessenger: binaryMessenger) - proxyApiRegistrar?.setUp() - } - public static func register(with registrar: FlutterPluginRegistrar) { - #if os(iOS) - let messenger = registrar.messenger() - #elseif os(macOS) - let messenger = registrar.messenger - #endif - - let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger) - - registrar.publish(plugin) - } - public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - proxyApiRegistrar?.ignoreCallsToDart = true - proxyApiRegistrar?.tearDown() - try? proxyApiRegistrar?.instanceManager.removeAllObjects() - proxyApiRegistrar = nil } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift deleted file mode 100644 index 6118b618d1e7..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - -#if os(iOS) - import Flutter - import UIKit -#elseif os(macOS) - import FlutterMacOS - import Foundation -#else - #error("Unsupported platform.") -#endif - -open class ProxyAPIRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar { - init( - binaryMessenger: FlutterBinaryMessenger, - ) { - super.init(binaryMessenger: binaryMessenger, apiDelegate: ProxyAPIDelegate()) - } - - // Log when a Flutter method receives an error from Dart. - func logFlutterMethodFailure(_ error: PigeonError, methodName: String) { - NSLog( - "\(String(describing: error)): Error returned from calling \(methodName): \(String(describing: error.message))" - ) - NSLog("%@", Thread.callStackSymbols.joined(separator: "\n")) - } - - /// Handles calling a Flutter method on the main thread. - func dispatchOnMainThread( - execute work: - @escaping ( - _ onFailure: @escaping (_ methodName: String, _ error: PigeonError) -> Void - ) -> Void - ) { - DispatchQueue.main.async { - work { methodName, error in - self.logFlutterMethodFailure(error, methodName: methodName) - } - } - } -} - -/// Implementation of `CrossFileDarwinApisPigeonProxyApiDelegate` that provides each ProxyApi delegate implementation. -class ProxyAPIDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { - func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) - -> PigeonApiAssetResourceReader - { - return PigeonApiAssetResourceReader( - pigeonRegistrar: registrar, delegate: AssetResourceReaderAPIDelegate()) - } -} diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift deleted file mode 100644 index 7b49a94e19a9..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/apiImplementations/AssetResourceReaderAPIDelegate.swift +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Foundation - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -private class AssetResourceReaderDelegateImpl: NSObject, AssetResourceReaderDelegate { - let api: PigeonApiProtocolAssetResourceReader - unowned let registrar: ProxyAPIRegistrar - - init(api: PigeonApiProtocolAssetResourceReader, registrar: ProxyAPIRegistrar) { - self.api = api - self.registrar = registrar - } - - func onDataReceived(reader: AssetResourceReader, bytes: Data) { - let data = FlutterStandardTypedData(bytes: bytes) - registrar.dispatchOnMainThread { onFailure in - self.api.onDataReceived(pigeonInstance: reader, bytes: data) { result in - if case .failure(let error) = result { - onFailure("AssetResourceReaderDelegate.onDataReceived", error) - } - } - } - } - - func onCompletion(reader: AssetResourceReader, error: String?) { - registrar.dispatchOnMainThread { onFailure in - self.api.onCompletion(pigeonInstance: reader, error: error) { result in - if case .failure(let error) = result { - onFailure("AssetResourceReaderDelegate.onCompletion", error) - } - } - } - } -} - -/// Implementation of `PigeonApiDelegateAssetResourceReader`. -class AssetResourceReaderAPIDelegate: PigeonApiDelegateAssetResourceReader { - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws - -> AssetResourceReader - { - let reader = AssetResourceReader() - reader.delegate = AssetResourceReaderDelegateImpl( - api: pigeonApi, registrar: pigeonApi.pigeonRegistrar as! ProxyAPIRegistrar) - return reader - } - - func startRead( - pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, - localIdentifier: String - ) throws -> Bool { - return pigeonInstance.startRead(localIdentifier: localIdentifier) - } -} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 2ecc9bd9d22c..35e764adcdc2 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -12,8 +12,7 @@ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 8F2171F72F21A5270014CE68 /* AssetResourceReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* AssetResourceReaderTests.swift */; }; - 8FF93F5B2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F5A2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift */; }; + 8F2171F72F21A5270014CE68 /* CrossFileDarwinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -54,8 +53,7 @@ 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../darwin/cross_file_darwin; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8F2171F52F21A5270014CE68 /* AssetResourceReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AssetResourceReaderTests.swift; path = ../../darwin/Tests/AssetResourceReaderTests.swift; sourceTree = SOURCE_ROOT; }; - 8FF93F5A2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = ../../darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = SOURCE_ROOT; }; + 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinTests.swift; path = ../../darwin/Tests/CrossFileDarwinTests.swift; sourceTree = SOURCE_ROOT; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -87,8 +85,7 @@ 331C8082294A63A400263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 8FF93F5A2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift */, - 8F2171F52F21A5270014CE68 /* AssetResourceReaderTests.swift */, + 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -296,8 +293,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F2171F72F21A5270014CE68 /* AssetResourceReaderTests.swift in Sources */, - 8FF93F5B2FE2F0C100F3D52F /* TestProxyAPIRegistrar.swift in Sources */, + 8F2171F72F21A5270014CE68 /* CrossFileDarwinTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index 356a47461c89..3a61fd5b1e39 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -27,8 +27,7 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 8FF93F5E2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F5D2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift */; }; - 8FF93F5F2FE2F63600F3D52F /* AssetResourceReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F5C2FE2F63600F3D52F /* AssetResourceReaderTests.swift */; }; + 8FF93F622FEB188300F3D52F /* CrossFileDarwinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F612FEB188300F3D52F /* CrossFileDarwinTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -81,9 +80,8 @@ 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../../darwin/cross_file_darwin; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; - 8FF93F5C2FE2F63600F3D52F /* AssetResourceReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AssetResourceReaderTests.swift; path = ../../darwin/Tests/AssetResourceReaderTests.swift; sourceTree = SOURCE_ROOT; }; - 8FF93F5D2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = TestProxyAPIRegistrar.swift; path = ../../darwin/Tests/TestProxyAPIRegistrar.swift; sourceTree = SOURCE_ROOT; }; 8FF93F602FE2F63800F3D52F /* RunnerTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RunnerTests-Bridging-Header.h"; sourceTree = ""; }; + 8FF93F612FEB188300F3D52F /* CrossFileDarwinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrossFileDarwinTests.swift; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -109,8 +107,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 8FF93F5C2FE2F63600F3D52F /* AssetResourceReaderTests.swift */, - 8FF93F5D2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift */, + 8FF93F612FEB188300F3D52F /* CrossFileDarwinTests.swift */, 8FF93F602FE2F63800F3D52F /* RunnerTests-Bridging-Header.h */, ); path = RunnerTests; @@ -356,8 +353,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8FF93F5E2FE2F63600F3D52F /* TestProxyAPIRegistrar.swift in Sources */, - 8FF93F5F2FE2F63600F3D52F /* AssetResourceReaderTests.swift in Sources */, + 8FF93F622FEB188300F3D52F /* CrossFileDarwinTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift new file mode 100644 index 000000000000..a222c2c29a14 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Testing + +@testable import cross_file_darwin + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +// Placeholder for adding tests. +struct CrossFileDarwinTests { + @Test func placeHoldertTest() throws { + #expect(true == true) + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart deleted file mode 100644 index f360e28c9d94..000000000000 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ /dev/null @@ -1,657 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// Autogenerated from Pigeon (v26.3.4), do not edit directly. -// See also: https://pub.dev/packages/pigeon -// ignore_for_file: unused_import, unused_shown_name -// ignore_for_file: type=lint - -import 'dart:async'; -import 'dart:io' show Platform; -import 'dart:typed_data' show Float64List, Int32List, Int64List; - -import 'package:flutter/services.dart'; -import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; -import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; - -Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, -}) { - if (replyList == null) { - throw PlatformException( - code: 'channel-error', - message: 'Unable to establish connection on channel: "$channelName".', - ); - } else if (replyList.length > 1) { - throw PlatformException( - code: replyList[0]! as String, - message: replyList[1] as String?, - details: replyList[2], - ); - } else if (!isNullValid && (replyList.isNotEmpty && replyList[0] == null)) { - throw PlatformException( - code: 'null-error', - message: 'Host platform returned null value for non-null return value.', - ); - } - return replyList.firstOrNull; -} - -List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { - if (empty) { - return []; - } - if (error == null) { - return [result]; - } - return [error.code, error.message, error.details]; -} - -/// Provides overrides for the constructors and static members of each -/// Dart proxy class. -/// -/// This is only intended to be used with unit tests to prevent errors from -/// making message calls in a unit test. -/// -/// See [PigeonOverrides.pigeon_reset] to set all overrides back to null. -@visibleForTesting -class PigeonOverrides { - /// Overrides [AssetResourceReader.new]. - static AssetResourceReader Function({ - required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, - required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, - })? - assetResourceReader_new; - - /// Sets all overridden ProxyApi class members to null. - static void pigeon_reset() { - assetResourceReader_new = null; - } -} - -/// An immutable object that serves as the base class for all Dart proxy classes -/// and can provide functional copies of itself. -/// -/// All implementers are expected to be [immutable] as defined by the annotation -/// and override [pigeon_copy] returning an instance of itself. -@immutable -abstract class PigeonInternalProxyApiBaseClass { - /// Construct a [PigeonInternalProxyApiBaseClass]. - PigeonInternalProxyApiBaseClass({ - this.pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = pigeon_instanceManager ?? PigeonInstanceManager.instance; - - /// Sends and receives binary data across the Flutter platform barrier. - /// - /// If it is null, the default BinaryMessenger will be used, which routes to - /// the host platform. - @protected - final BinaryMessenger? pigeon_binaryMessenger; - - /// Maintains instances stored to communicate with native language objects. - final PigeonInstanceManager pigeon_instanceManager; - - /// Instantiates and returns a functionally identical object to oneself. - /// - /// Outside of tests, this method should only ever be called by - /// [PigeonInstanceManager]. - /// - /// Subclasses should always override their parent's implementation of this - /// method. - @protected - PigeonInternalProxyApiBaseClass pigeon_copy(); -} - -/// Maintains instances used to communicate with the native objects they -/// represent. -/// -/// Added instances are stored as weak references and their copies are stored -/// as strong references to maintain access to their variables and callback -/// methods. Both are stored with the same identifier. -/// -/// When a weak referenced instance becomes inaccessible, -/// [onWeakReferenceRemoved] is called with its associated identifier. -/// -/// If an instance is retrieved and has the possibility to be used, -/// (e.g. calling [getInstanceWithWeakReference]) a copy of the strong reference -/// is added as a weak reference with the same identifier. This prevents a -/// scenario where the weak referenced instance was released and then later -/// returned by the host platform. -class PigeonInstanceManager { - /// Constructs a [PigeonInstanceManager]. - PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { - this.onWeakReferenceRemoved = (int identifier) { - _weakInstances.remove(identifier); - onWeakReferenceRemoved(identifier); - }; - _finalizer = Finalizer(this.onWeakReferenceRemoved); - } - - // Identifiers are locked to a specific range to avoid collisions with objects - // created simultaneously by the host platform. - // Host uses identifiers >= 2^16 and Dart is expected to use values n where, - // 0 <= n < 2^16. - static const int _maxDartCreatedIdentifier = 65536; - - /// The default [PigeonInstanceManager] used by Dart proxy classes. - /// - /// On creation, this manager makes a call to clear the native - /// InstanceManager. This is to prevent identifier conflicts after a host - /// restart. - static final PigeonInstanceManager instance = _initInstance(); - - // Expando is used because it doesn't prevent its keys from becoming - // inaccessible. This allows the manager to efficiently retrieve an identifier - // of an instance without holding a strong reference to that instance. - // - // It also doesn't use `==` to search for identifiers, which would lead to an - // infinite loop when comparing an object to its copy. (i.e. which was caused - // by calling instanceManager.getIdentifier() inside of `==` while this was a - // HashMap). - final Expando _identifiers = Expando(); - final Map> _weakInstances = - >{}; - final Map _strongInstances = - {}; - late final Finalizer _finalizer; - int _nextIdentifier = 0; - - /// Called when a weak referenced instance is removed by [removeWeakReference] - /// or becomes inaccessible. - late final void Function(int) onWeakReferenceRemoved; - - static PigeonInstanceManager _initInstance() { - if (Platform.environment['FLUTTER_TEST'] == 'true') { - return PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); - } - WidgetsFlutterBinding.ensureInitialized(); - final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); - // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. - api.clear(); - final PigeonInstanceManager instanceManager = PigeonInstanceManager( - onWeakReferenceRemoved: (int identifier) { - api.removeStrongReference(identifier); - }, - ); - _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); - AssetResourceReader.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - return instanceManager; - } - - /// Adds a new instance that was instantiated by Dart. - /// - /// In other words, Dart wants to add a new instance that will represent - /// an object that will be instantiated on the host platform. - /// - /// Throws assertion error if the instance has already been added. - /// - /// Returns the randomly generated id of the [instance] added. - int addDartCreatedInstance(PigeonInternalProxyApiBaseClass instance) { - assert(getIdentifier(instance) == null); - - final int identifier = _nextUniqueIdentifier(); - _identifiers[instance] = identifier; - _weakInstances[identifier] = WeakReference(instance); - _finalizer.attach(instance, identifier, detach: instance); - - final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); - _identifiers[copy] = identifier; - _strongInstances[identifier] = copy; - return identifier; - } - - /// Removes the instance, if present, and call [onWeakReferenceRemoved] with - /// its identifier. - /// - /// Returns the identifier associated with the removed instance. Otherwise, - /// `null` if the instance was not found in this manager. - /// - /// This does not remove the strong referenced instance associated with - /// [instance]. This can be done with [remove]. - int? removeWeakReference(PigeonInternalProxyApiBaseClass instance) { - final int? identifier = getIdentifier(instance); - if (identifier == null) { - return null; - } - - _identifiers[instance] = null; - _finalizer.detach(instance); - onWeakReferenceRemoved(identifier); - - return identifier; - } - - /// Removes [identifier] and its associated strongly referenced instance, if - /// present, from the manager. - /// - /// Returns the strong referenced instance associated with [identifier] before - /// it was removed. Returns `null` if [identifier] was not associated with - /// any strong reference. - /// - /// Throws an `AssertionError` if the weak referenced instance associated with - /// [identifier] is not removed first. This can be done with - /// [removeWeakReference]. - T? remove(int identifier) { - final T? instance = _weakInstances[identifier]?.target as T?; - assert( - instance == null, - 'A strong instance with identifier $identifier is being removed despite the weak reference still existing: $instance', - ); - return _strongInstances.remove(identifier) as T?; - } - - /// Retrieves the instance associated with identifier. - /// - /// The value returned is chosen from the following order: - /// - /// 1. A weakly referenced instance associated with identifier. - /// 2. If the only instance associated with identifier is a strongly - /// referenced instance, a copy of the instance is added as a weak reference - /// with the same identifier. Returning the newly created copy. - /// 3. If no instance is associated with identifier, returns null. - /// - /// This method also expects the host `InstanceManager` to have a strong - /// reference to the instance the identifier is associated with. - T? getInstanceWithWeakReference(int identifier) { - final PigeonInternalProxyApiBaseClass? weakInstance = _weakInstances[identifier]?.target; - - if (weakInstance == null) { - final PigeonInternalProxyApiBaseClass? strongInstance = _strongInstances[identifier]; - if (strongInstance != null) { - final PigeonInternalProxyApiBaseClass copy = strongInstance.pigeon_copy(); - _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); - _finalizer.attach(copy, identifier, detach: copy); - return copy as T; - } - return strongInstance as T?; - } - - return weakInstance as T; - } - - /// Retrieves the identifier associated with instance. - int? getIdentifier(PigeonInternalProxyApiBaseClass instance) { - return _identifiers[instance]; - } - - /// Adds a new instance that was instantiated by the host platform. - /// - /// In other words, the host platform wants to add a new instance that - /// represents an object on the host platform. Stored with [identifier]. - /// - /// Throws assertion error if the instance or its identifier has already been - /// added. - void addHostCreatedInstance(PigeonInternalProxyApiBaseClass instance, int identifier) { - assert(!containsIdentifier(identifier)); - assert(getIdentifier(instance) == null); - assert(identifier >= 0); - - _identifiers[instance] = identifier; - _strongInstances[identifier] = instance; - } - - /// Whether this manager contains the given [identifier]. - bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || _strongInstances.containsKey(identifier); - } - - int _nextUniqueIdentifier() { - late int identifier; - do { - identifier = _nextIdentifier; - _nextIdentifier = (_nextIdentifier + 1) % _maxDartCreatedIdentifier; - } while (containsIdentifier(identifier)); - return identifier; - } -} - -/// Generated API for managing the Dart and native `PigeonInstanceManager`s. -class _PigeonInternalInstanceManagerApi { - /// Constructor for [_PigeonInternalInstanceManagerApi]. - _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; - - final BinaryMessenger? pigeonVar_binaryMessenger; - - static const MessageCodec pigeonChannelCodec = _PigeonCodec(); - - static void setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? binaryMessenger, - PigeonInstanceManager? instanceManager, - }) { - { - final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - final List args = message! as List; - final int arg_identifier = args[0]! as int; - try { - (instanceManager ?? PigeonInstanceManager.instance).remove(arg_identifier); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); - } - }); - } - } - } - - Future removeStrongReference(int identifier) async { - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([identifier]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); - } - - /// Clear the native `PigeonInstanceManager`. - /// - /// This is typically called after a hot restart. - Future clear() async { - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); - } -} - -class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager.getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - -class _PigeonCodec extends StandardMessageCodec { - const _PigeonCodec(); - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is int) { - buffer.putUint8(4); - buffer.putInt64(value); - } else { - super.writeValue(buffer, value); - } - } - - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - default: - return super.readValueOfType(type, buffer); - } - } -} - -/// Class for handling an instance of asynchronously reading bytes from -/// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). -class AssetResourceReader extends PigeonInternalProxyApiBaseClass { - factory AssetResourceReader({ - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - required void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived, - required void Function(AssetResourceReader pigeon_instance, String? error) onCompletion, - }) { - if (PigeonOverrides.assetResourceReader_new != null) { - return PigeonOverrides.assetResourceReader_new!( - onDataReceived: onDataReceived, - onCompletion: onCompletion, - ); - } - return AssetResourceReader.pigeon_new( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - onDataReceived: onDataReceived, - onCompletion: onCompletion, - ); - } - - @protected - AssetResourceReader.pigeon_new({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - required this.onDataReceived, - required this.onCompletion, - }) { - final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([ - pigeonVar_instanceIdentifier, - ]); - () async { - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); - }(); - } - - /// Constructs [AssetResourceReader] without creating the associated native object. - /// - /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInstanceManager]. - @protected - AssetResourceReader.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - required this.onDataReceived, - required this.onCompletion, - }); - - late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceReader = - _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); - - /// Provides the requested data. - /// - /// Called multiple times until all bytes are received. - /// - /// Corresponds to the `dataReceivedHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - /// - /// For the associated Native object to be automatically garbage collected, - /// it is required that the implementation of this `Function` doesn't have a - /// strong reference to the encapsulating class instance. When this `Function` - /// references a non-local variable, it is strongly recommended to access it - /// with a `WeakReference`: - /// - /// ```dart - /// final WeakReference weakMyVariable = WeakReference(myVariable); - /// final AssetResourceReader instance = AssetResourceReader( - /// onDataReceived: (AssetResourceReader pigeon_instance, ...) { - /// print(weakMyVariable?.target); - /// }, - /// ); - /// ``` - /// - /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to - /// release the associated Native object manually. - final void Function(AssetResourceReader pigeon_instance, Uint8List bytes) onDataReceived; - - /// Indicates the request for data has completed. - /// - /// Called once after the request has been fulfilled or has failed. - /// - /// Corresponds to the `completionHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - /// - /// For the associated Native object to be automatically garbage collected, - /// it is required that the implementation of this `Function` doesn't have a - /// strong reference to the encapsulating class instance. When this `Function` - /// references a non-local variable, it is strongly recommended to access it - /// with a `WeakReference`: - /// - /// ```dart - /// final WeakReference weakMyVariable = WeakReference(myVariable); - /// final AssetResourceReader instance = AssetResourceReader( - /// onCompletion: (AssetResourceReader pigeon_instance, ...) { - /// print(weakMyVariable?.target); - /// }, - /// ); - /// ``` - /// - /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to - /// release the associated Native object manually. - final void Function(AssetResourceReader pigeon_instance, String? error) onCompletion; - - static void pigeon_setUpMessageHandlers({ - bool pigeon_clearHandlers = false, - BinaryMessenger? pigeon_binaryMessenger, - PigeonInstanceManager? pigeon_instanceManager, - void Function(AssetResourceReader pigeon_instance, Uint8List bytes)? onDataReceived, - void Function(AssetResourceReader pigeon_instance, String? error)? onCompletion, - }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance, - ); - final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; - { - final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onDataReceived', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - final List args = message! as List; - final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; - final Uint8List arg_bytes = args[1]! as Uint8List; - try { - (onDataReceived ?? arg_pigeon_instance.onDataReceived).call( - arg_pigeon_instance, - arg_bytes, - ); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); - } - }); - } - } - - { - final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.onCompletion', - pigeonChannelCodec, - binaryMessenger: binaryMessenger, - ); - if (pigeon_clearHandlers) { - pigeonVar_channel.setMessageHandler(null); - } else { - pigeonVar_channel.setMessageHandler((Object? message) async { - final List args = message! as List; - final AssetResourceReader arg_pigeon_instance = args[0]! as AssetResourceReader; - final String? arg_error = args[1] as String?; - try { - (onCompletion ?? arg_pigeon_instance.onCompletion).call(arg_pigeon_instance, arg_error); - return wrapResponse(empty: true); - } on PlatformException catch (e) { - return wrapResponse(error: e); - } catch (e) { - return wrapResponse( - error: PlatformException(code: 'error', message: e.toString()), - ); - } - }); - } - } - } - - /// Start reading bytes from the asset with the given identifier. - /// - /// Returns false if the resource for the identifier could not be accessed or - /// found. Returns true if the resource can be successfully accessed. - /// - /// Bytes are passed to `onDataReceived` and the request is completed when - /// `onCompletion` is called. - Future startRead(String localIdentifier) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; - final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; - const pigeonVar_channelName = - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.startRead'; - final pigeonVar_channel = BasicMessageChannel( - pigeonVar_channelName, - pigeonChannelCodec, - binaryMessenger: pigeonVar_binaryMessenger, - ); - final Future pigeonVar_sendFuture = pigeonVar_channel.send([ - this, - localIdentifier, - ]); - final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - - final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: false, - ); - return pigeonVar_replyValue! as bool; - } - - @override - AssetResourceReader pigeon_copy() { - return AssetResourceReader.pigeon_detached( - pigeon_binaryMessenger: pigeon_binaryMessenger, - pigeon_instanceManager: pigeon_instanceManager, - onDataReceived: onDataReceived, - onCompletion: onCompletion, - ); - } -} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 0cc24efe549c..f778083c471a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -14,7 +14,6 @@ import 'package:flutter/foundation.dart'; import 'package:objective_c/objective_c.dart'; import 'package:path/path.dart' as path; -import 'cross_file_darwin_apis.g.dart'; import 'ffi_bindings.g.dart'; import 'security_scoped_resource.dart'; @@ -198,18 +197,28 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile return null; } - // TODO(bparrishMines): Implementation should be switched to use `ffigen`. - // Blocked by https://github.com/dart-lang/native/issues/3416. @override Stream openRead([int? start, int? end]) { assert(start == null || start >= 0); assert(end == null || end >= (start ?? 0)); final streamController = StreamController(); + + final PHAssetResource? resource = _tryGetAssetResource(identifier: params.uri); + if (resource == null) { + streamController.addError( + Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), + ); + streamController.close(); + return streamController.stream; + } + var currentByteIndex = 0; - final reader = AssetResourceReader( - onDataReceived: (_, Uint8List bytes) { + void dataReceivedHandler(NSData data) { + final Uint8List bytes = _extractBytesToUint8List(data); + + runOnPlatformThread(() { final int newByteIndex = currentByteIndex + bytes.length; final int startOrZero = start ?? 0; @@ -239,24 +248,25 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } currentByteIndex = newByteIndex; - }, - onCompletion: (_, String? error) { + }); + } + + void completionHandler(NSError? error) { + runOnPlatformThread(() { if (error != null) { - streamController.addError(Exception(error)); + streamController.addError(Exception(error.localizedDescription.toDartString())); } - streamController.close(); - }, + return streamController.close(); + }); + } + + PHAssetResourceManager.defaultManager().requestDataForAssetResource( + resource, + dataReceivedHandler: ObjCBlock_ffiVoid_NSData.blocking(dataReceivedHandler), + completionHandler: ObjCBlock_ffiVoid_NSError.blocking(completionHandler), ); - reader.startRead(params.uri).then((bool canRead) { - if (!canRead) { - streamController.addError( - Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), - ); - streamController.close(); - } - }); return streamController.stream; } diff --git a/packages/cross_file/cross_file_darwin/pigeons/copyright.txt b/packages/cross_file/cross_file_darwin/pigeons/copyright.txt deleted file mode 100644 index 07e5f8598a80..000000000000 --- a/packages/cross_file/cross_file_darwin/pigeons/copyright.txt +++ /dev/null @@ -1,3 +0,0 @@ -Copyright 2013 The Flutter Authors -Use of this source code is governed by a BSD-style license that can be -found in the LICENSE file. diff --git a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart b/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart deleted file mode 100644 index 316c4db6ed2c..000000000000 --- a/packages/cross_file/cross_file_darwin/pigeons/cross_file_darwin_apis.dart +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ignore_for_file: avoid_unused_constructor_parameters - -import 'package:pigeon/pigeon.dart'; - -@ConfigurePigeon( - PigeonOptions( - dartOut: 'lib/src/cross_file_darwin_apis.g.dart', - swiftOut: 'darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift', - copyrightHeader: 'pigeons/copyright.txt', - ), -) -/// Class for handling an instance of asynchronously reading bytes from -/// [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). -@ProxyApi() -abstract class AssetResourceReader { - AssetResourceReader(); - - /// Provides the requested data. - /// - /// Called multiple times until all bytes are received. - /// - /// Corresponds to the `dataReceivedHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - late final void Function(Uint8List bytes) onDataReceived; - - /// Indicates the request for data has completed. - /// - /// Called once after the request has been fulfilled or has failed. - /// - /// Corresponds to the `completionHandler` parameter for - /// `PHAssetResourceManager.requestDataForAssetResource`. - late final void Function(String? error) onCompletion; - - /// Start reading bytes from the asset with the given identifier. - /// - /// Returns false if the resource for the identifier could not be accessed or - /// found. Returns true if the resource can be successfully accessed. - /// - /// Bytes are passed to `onDataReceived` and the request is completed when - /// `onCompletion` is called. - bool startRead(String localIdentifier); -} diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 5d717163ed43..378a6f9c6f12 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -40,12 +40,9 @@ dependencies: path: ^1.9.1 dev_dependencies: - build_runner: ^2.10.4 ffigen: ^20.1.1 flutter_test: sdk: flutter - mockito: ^5.4.4 - pigeon: ^26.1.4 topics: - file diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart deleted file mode 100644 index a93ccf67b690..000000000000 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:typed_data'; - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; -import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:mockito/annotations.dart'; -import 'package:mockito/mockito.dart'; - -import 'photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart'; - -@GenerateMocks([AssetResourceReader]) -void main() { - setUp(() { - PigeonOverrides.pigeon_reset(); - }); - - group('openRead', () { - test('correctly reads all bytes with null start and null end', () async { - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), - ); - - final MockAssetResourceReader reader = setUpReader(); - - final Stream stream = file.openRead(); - - final bytes = Uint8List.fromList([1, 2, 3]); - reader.onDataReceived(reader, bytes); - reader.onCompletion(reader, null); - - expect( - await stream.reduce( - (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), - ), - bytes, - ); - }); - - test('correctly reads desired sublist', () async { - final file = DarwinScopedStorageXFile( - DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), - ); - - final MockAssetResourceReader reader = setUpReader(); - - final bytes = Uint8List.fromList([0, 1, 2, 3, 4]); - final Stream stream = file.openRead(1, 4); - - // Ignore byte before desired sublist. - reader.onDataReceived(reader, Uint8List.fromList([bytes[0]])); - // Read byte at start of desired sublist. - reader.onDataReceived(reader, Uint8List.fromList([bytes[1]])); - // Read byte between start and end of desired sublist. - reader.onDataReceived(reader, Uint8List.fromList([bytes[2]])); - // Read byte at end of desire sublist - reader.onDataReceived(reader, Uint8List.fromList([bytes[3]])); - // Ignore byte after desired sublist. - reader.onDataReceived(reader, Uint8List.fromList([bytes[4]])); - reader.onCompletion(reader, null); - - expect( - await stream.reduce( - (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), - ), - bytes.sublist(1, 4), - ); - }); - }); -} - -MockAssetResourceReader setUpReader() { - final reader = MockAssetResourceReader(); - when(reader.startRead('id')).thenAnswer((_) async { - return true; - }); - - PigeonOverrides.assetResourceReader_new = - ({ - required void Function(AssetResourceReader instance, Uint8List bytes) onDataReceived, - required void Function(AssetResourceReader instance, String? error) onCompletion, - }) { - when(reader.onDataReceived).thenReturn(onDataReceived); - when(reader.onCompletion).thenReturn(onCompletion); - return reader; - }; - - return reader; -} diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart deleted file mode 100644 index cb302e37f3cb..000000000000 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart +++ /dev/null @@ -1,87 +0,0 @@ -// Mocks generated by Mockito 5.4.6 from annotations -// in cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart. -// Do not manually edit this file. - -// ignore_for_file: no_leading_underscores_for_library_prefixes -import 'dart:async' as _i4; -import 'dart:typed_data' as _i3; - -import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; -import 'package:mockito/mockito.dart' as _i1; - -// ignore_for_file: type=lint -// ignore_for_file: avoid_redundant_argument_values -// ignore_for_file: avoid_setters_without_getters -// ignore_for_file: comment_references -// ignore_for_file: deprecated_member_use -// ignore_for_file: deprecated_member_use_from_same_package -// ignore_for_file: implementation_imports -// ignore_for_file: invalid_use_of_visible_for_testing_member -// ignore_for_file: must_be_immutable -// ignore_for_file: prefer_const_constructors -// ignore_for_file: unnecessary_parenthesis -// ignore_for_file: camel_case_types -// ignore_for_file: subtype_of_sealed_class -// ignore_for_file: invalid_use_of_internal_member - -class _FakePigeonInstanceManager_0 extends _i1.SmartFake implements _i2.PigeonInstanceManager { - _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -class _FakeAssetResourceReader_1 extends _i1.SmartFake implements _i2.AssetResourceReader { - _FakeAssetResourceReader_1(Object parent, Invocation parentInvocation) - : super(parent, parentInvocation); -} - -/// A class which mocks [AssetResourceReader]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockAssetResourceReader extends _i1.Mock implements _i2.AssetResourceReader { - MockAssetResourceReader() { - _i1.throwOnMissingStub(this); - } - - @override - void Function(_i2.AssetResourceReader, _i3.Uint8List) get onDataReceived => - (super.noSuchMethod( - Invocation.getter(#onDataReceived), - returnValue: (_i2.AssetResourceReader pigeon_instance, _i3.Uint8List bytes) {}, - ) - as void Function(_i2.AssetResourceReader, _i3.Uint8List)); - - @override - void Function(_i2.AssetResourceReader, String?) get onCompletion => - (super.noSuchMethod( - Invocation.getter(#onCompletion), - returnValue: (_i2.AssetResourceReader pigeon_instance, String? error) {}, - ) - as void Function(_i2.AssetResourceReader, String?)); - - @override - _i2.PigeonInstanceManager get pigeon_instanceManager => - (super.noSuchMethod( - Invocation.getter(#pigeon_instanceManager), - returnValue: _FakePigeonInstanceManager_0( - this, - Invocation.getter(#pigeon_instanceManager), - ), - ) - as _i2.PigeonInstanceManager); - - @override - _i4.Future startRead(String? localIdentifier) => - (super.noSuchMethod( - Invocation.method(#startRead, [localIdentifier]), - returnValue: _i4.Future.value(false), - ) - as _i4.Future); - - @override - _i2.AssetResourceReader pigeon_copy() => - (super.noSuchMethod( - Invocation.method(#pigeon_copy, []), - returnValue: _FakeAssetResourceReader_1(this, Invocation.method(#pigeon_copy, [])), - ) - as _i2.AssetResourceReader); -} From a2d34bd3cd9bc88976bfd0055deb54c187433f39 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 15:44:36 -0400 Subject: [PATCH 319/398] use ffigen --- .../ios/Runner.xcodeproj/project.pbxproj | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 10 ++++----- .../RunnerTests/CrossFileDarwinTests.swift | 22 ------------------- 3 files changed, 6 insertions(+), 28 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 35e764adcdc2..38eaae5d15d7 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index 3a61fd5b1e39..ca64b45abafe 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -27,7 +27,7 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 8FF93F622FEB188300F3D52F /* CrossFileDarwinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F612FEB188300F3D52F /* CrossFileDarwinTests.swift */; }; + 8FF93F642FEB191200F3D52F /* CrossFileDarwinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FF93F632FEB191200F3D52F /* CrossFileDarwinTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -81,7 +81,7 @@ 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; 8FF93F602FE2F63800F3D52F /* RunnerTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RunnerTests-Bridging-Header.h"; sourceTree = ""; }; - 8FF93F612FEB188300F3D52F /* CrossFileDarwinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrossFileDarwinTests.swift; sourceTree = ""; }; + 8FF93F632FEB191200F3D52F /* CrossFileDarwinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinTests.swift; path = ../../darwin/Tests/CrossFileDarwinTests.swift; sourceTree = SOURCE_ROOT; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; /* End PBXFileReference section */ @@ -107,7 +107,7 @@ 331C80D6294CF71000263BE5 /* RunnerTests */ = { isa = PBXGroup; children = ( - 8FF93F612FEB188300F3D52F /* CrossFileDarwinTests.swift */, + 8FF93F632FEB191200F3D52F /* CrossFileDarwinTests.swift */, 8FF93F602FE2F63800F3D52F /* RunnerTests-Bridging-Header.h */, ); path = RunnerTests; @@ -353,7 +353,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8FF93F622FEB188300F3D52F /* CrossFileDarwinTests.swift in Sources */, + 8FF93F642FEB191200F3D52F /* CrossFileDarwinTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift b/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift deleted file mode 100644 index a222c2c29a14..000000000000 --- a/packages/cross_file/cross_file_darwin/example/macos/RunnerTests/CrossFileDarwinTests.swift +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Testing - -@testable import cross_file_darwin - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -// Placeholder for adding tests. -struct CrossFileDarwinTests { - @Test func placeHoldertTest() throws { - #expect(true == true) - } -} From 8517b1bda3ab366ea480c8e30debcba587983b8a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 15:51:26 -0400 Subject: [PATCH 320/398] add flutter deps --- .../darwin/cross_file_darwin/Package.swift | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift index d83ea024bece..99e9317f5f88 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Package.swift @@ -15,12 +15,15 @@ let package = Package( products: [ .library(name: "cross-file-darwin", targets: ["cross_file_darwin"]) ], - dependencies: [], + dependencies: [ + .package(name: "FlutterFramework", path: "../FlutterFramework") + ], targets: [ .target( name: "cross_file_darwin", dependencies: [ - "cross_file_darwin_objc" + "cross_file_darwin_objc", + .product(name: "FlutterFramework", package: "FlutterFramework"), ], resources: [ .process("Resources") From 44e06768ff86ba700df23365ca2ec1d11595b5d3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:12:18 -0400 Subject: [PATCH 321/398] add dart test yaml --- packages/cross_file/cross_file_web/dart_test.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 packages/cross_file/cross_file_web/dart_test.yaml diff --git a/packages/cross_file/cross_file_web/dart_test.yaml b/packages/cross_file/cross_file_web/dart_test.yaml new file mode 100644 index 000000000000..a883822278f5 --- /dev/null +++ b/packages/cross_file/cross_file_web/dart_test.yaml @@ -0,0 +1,6 @@ +# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments +override_platforms: + chrome: + settings: + executable: chrome + arguments: --no-sandbox \ No newline at end of file From 356487af303de820d71383e0e4de43e982d7bba9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:12:57 -0400 Subject: [PATCH 322/398] rename to actual file name --- ...oss_file_test.dart => web_scoped_storage_cross_file_test.dart} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/cross_file/cross_file_web/test/{web_cross_file_test.dart => web_scoped_storage_cross_file_test.dart} (100%) diff --git a/packages/cross_file/cross_file_web/test/web_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart similarity index 100% rename from packages/cross_file/cross_file_web/test/web_cross_file_test.dart rename to packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart From 1b2f3613284f8e396d703401b4d51e9ad77045ce Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 16:44:30 -0400 Subject: [PATCH 323/398] delete --- packages/cross_file/cross_file_web/dart_test.yaml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 packages/cross_file/cross_file_web/dart_test.yaml diff --git a/packages/cross_file/cross_file_web/dart_test.yaml b/packages/cross_file/cross_file_web/dart_test.yaml deleted file mode 100644 index a883822278f5..000000000000 --- a/packages/cross_file/cross_file_web/dart_test.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# See https://github.com/dart-lang/test/blob/master/pkgs/test/doc/configuration.md#arguments -override_platforms: - chrome: - settings: - executable: chrome - arguments: --no-sandbox \ No newline at end of file From 50cffbeb49d329deb2929b20ba8735adfbc2bff5 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:24:38 -0400 Subject: [PATCH 324/398] fix integration test macos --- .../example/macos/Runner/Configs/Debug.xcconfig | 1 + .../example/macos/Runner/Configs/Release.xcconfig | 1 + .../example/macos/Runner.xcodeproj/project.pbxproj | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig index 786963738d3e..36b0fd9464f4 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Debug.xcconfig @@ -1 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" #include "Warnings.xcconfig" diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig index 786963738d3e..dff4f49561c8 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner/Configs/Release.xcconfig @@ -1 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" #include "Warnings.xcconfig" diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj index 115f5c2b3249..858185a5ce46 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ From ace90a22a447597c5c093f00bf6ae2cbd7e7c0c8 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:28:24 -0400 Subject: [PATCH 325/398] remove chrome requirement --- .../test/web_scoped_storage_cross_file_test.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart index 4647b5b81acb..d7558b342257 100644 --- a/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -@TestOn('chrome') // Uses web-only Flutter SDK -library; - import 'dart:convert'; import 'dart:js_interop'; import 'dart:typed_data'; From a0a4c853d9a468364c83ea44622ff14e7692a52a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 23 Jun 2026 19:57:15 -0400 Subject: [PATCH 326/398] move tests to integration tests --- .../integration_test/cross_file_web_test.dart | 210 ++++++++++++++++- .../cross_file_web/example/pubspec.yaml | 11 + .../cross_file/cross_file_web/test/README.md | 5 + .../test/tests_exist_elsewhere_test.dart | 16 ++ .../web_scoped_storage_cross_file_test.dart | 215 ------------------ 5 files changed, 239 insertions(+), 218 deletions(-) create mode 100644 packages/cross_file/cross_file_web/test/README.md create mode 100644 packages/cross_file/cross_file_web/test/tests_exist_elsewhere_test.dart delete mode 100644 packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart diff --git a/packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart b/packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart index 621977be68c7..be5c149d1b2d 100644 --- a/packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart +++ b/packages/cross_file/cross_file_web/example/integration_test/cross_file_web_test.dart @@ -2,13 +2,217 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:convert'; +import 'dart:js_interop'; +import 'dart:typed_data'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:cross_file_web/cross_file_web.dart'; +import 'package:cross_file_web/src/web_helpers.dart'; +import 'package:cross_file_web/src/web_scoped_storage_cross_file.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:web/web.dart' as html; + +const String testFileStringContents = 'Hello, world! I ❤ ñ! 空手'; +final Uint8List testFileBytes = Uint8List.fromList(utf8.encode(testFileStringContents)); +final html.File testFile = html.File([testFileBytes.toJS].toJS, 'hello.txt'); +final String testFileUrl = html.URL.createObjectURL(testFile as JSObject); void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - // Since this test is lacking integration tests, this test ensures the example - // app can be launched on an emulator/device. - testWidgets('Launch Test', (WidgetTester tester) async {}); + group('WebScopedStorageXFile', () { + CrossFilePlatform.instance = CrossFileWeb(); + + group('Create with url', () { + testWidgets('openRead', (_) async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), + ); + + expect(await file.openRead().first, testFileBytes); + }); + + testWidgets('openRead with partial data', (_) async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), + ); + + expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); + }); + + testWidgets('readAsBytes', (_) async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), + ); + + expect(await file.readAsBytes(), testFileBytes); + }); + + testWidgets('readAsString', (_) async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), + ); + + expect(await file.readAsString(), testFileStringContents); + }); + + testWidgets('canRead', (_) async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), + ); + + expect(await file.canRead(), true); + }); + + testWidgets('exists', (_) async { + final file = PlatformScopedStorageXFile( + PlatformScopedStorageXFileCreationParams(uri: testFileUrl), + ); + + expect(await file.exists(), true); + }); + }); + + group('Create with File', () { + testWidgets('lastModified', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect( + await file.lastModified(), + DateTime.fromMillisecondsSinceEpoch(testFile.lastModified), + ); + }); + + testWidgets('length', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.length(), testFile.size); + }); + + testWidgets('openRead', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.openRead().first, testFileBytes); + }); + + testWidgets('openRead with partial data', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); + }); + + testWidgets('readAsBytes', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.readAsBytes(), testFileBytes); + }); + + testWidgets('readAsString', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.readAsString(), testFileStringContents); + }); + + testWidgets('exists', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.exists(), true); + }); + + testWidgets('name', (_) async { + final file = PlatformScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile), + ); + + expect(await file.name(), testFile.name); + }); + }); + + group('download', () { + const crossFileDomElementId = '__x_file_dom_element'; + + group('XFile download', () { + testWidgets('creates a DOM container', (_) async { + final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; + final testOverrides = XFileTestOverrides(createAnchorElement: (_, _) => mockAnchor); + + final file = WebScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), + ); + + await file.download(); + + final html.Element? container = html.document.querySelector('#$crossFileDomElementId'); + + expect(container, isNotNull); + }); + + testWidgets('create anchor element', (_) async { + final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; + late final String setHref; + late final String? setDownload; + final testOverrides = XFileTestOverrides( + createAnchorElement: (String href, String? suggestedName) { + setHref = href; + setDownload = suggestedName; + return mockAnchor; + }, + ); + + final file = WebScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), + ); + + await file.download('path'); + + final html.Element container = html.document.querySelector('#$crossFileDomElementId')!; + + // Find anchor element. + late final html.HTMLAnchorElement element; + for (var i = 0; i < container.childNodes.length; i++) { + element = container.children.item(i)! as html.HTMLAnchorElement; + } + + // If element is not found, the `firstWhere` call will throw StateError. + expect(element, mockAnchor); + expect(element.tagName, 'A'); + expect(setHref, file.params.uri); + expect(setDownload, 'path'); + }); + + testWidgets('anchor element is clicked', (_) async { + final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; + + final testOverrides = XFileTestOverrides(createAnchorElement: (_, _) => mockAnchor); + + final file = WebScopedStorageXFile( + WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), + ); + + var clicked = false; + mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); + + await file.download('path'); + + expect(clicked, true); + }); + }); + }); + }); } diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index 6a673fcbf740..ef662828263f 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -16,10 +16,21 @@ dependencies: mime: ^2.0.0 dev_dependencies: + cross_file_platform_interface: + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_platform_interface + cross_file_web: + git: + url: https://github.com/bparrishMines/packages + ref: new_crossfile + path: packages/cross_file/cross_file_web flutter_test: sdk: flutter integration_test: sdk: flutter + web: ">=0.5.1 <2.0.0" dependency_overrides: # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because diff --git a/packages/cross_file/cross_file_web/test/README.md b/packages/cross_file/cross_file_web/test/README.md new file mode 100644 index 000000000000..7c5b4ad682ba --- /dev/null +++ b/packages/cross_file/cross_file_web/test/README.md @@ -0,0 +1,5 @@ +## test + +This package uses integration tests for testing. + +See `example/README.md` for more info. diff --git a/packages/cross_file/cross_file_web/test/tests_exist_elsewhere_test.dart b/packages/cross_file/cross_file_web/test/tests_exist_elsewhere_test.dart new file mode 100644 index 000000000000..fe15f1088c98 --- /dev/null +++ b/packages/cross_file/cross_file_web/test/tests_exist_elsewhere_test.dart @@ -0,0 +1,16 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// ignore_for_file: avoid_print + +import 'package:flutter_test/flutter_test.dart'; + +void main() { + test('Tell the user where to find the real tests', () { + print('---'); + print('This package uses integration_test for its tests.'); + print('See `example/README.md` for more info.'); + print('---'); + }); +} diff --git a/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart deleted file mode 100644 index d7558b342257..000000000000 --- a/packages/cross_file/cross_file_web/test/web_scoped_storage_cross_file_test.dart +++ /dev/null @@ -1,215 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:js_interop'; -import 'dart:typed_data'; - -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:cross_file_web/cross_file_web.dart'; -import 'package:cross_file_web/src/web_helpers.dart'; -import 'package:cross_file_web/src/web_scoped_storage_cross_file.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:web/web.dart' as html; - -const String testFileStringContents = 'Hello, world! I ❤ ñ! 空手'; -final Uint8List testFileBytes = Uint8List.fromList(utf8.encode(testFileStringContents)); -final html.File testFile = html.File([testFileBytes.toJS].toJS, 'hello.txt'); -final String testFileUrl = html.URL.createObjectURL(testFile as JSObject); - -void main() { - group('WebScopedStorageXFile', () { - CrossFilePlatform.instance = CrossFileWeb(); - - group('Create with url', () { - test('openRead', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFileUrl), - ); - - expect(await file.openRead().first, testFileBytes); - }); - - test('openRead with partial data', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFileUrl), - ); - - expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); - }); - - test('readAsBytes', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFileUrl), - ); - - expect(await file.readAsBytes(), testFileBytes); - }); - - test('readAsString', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFileUrl), - ); - - expect(await file.readAsString(), testFileStringContents); - }); - - test('canRead', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFileUrl), - ); - - expect(await file.canRead(), true); - }); - - test('exists', () async { - final file = PlatformScopedStorageXFile( - PlatformScopedStorageXFileCreationParams(uri: testFileUrl), - ); - - expect(await file.exists(), true); - }); - }); - - group('Create with File', () { - test('lastModified', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect( - await file.lastModified(), - DateTime.fromMillisecondsSinceEpoch(testFile.lastModified), - ); - }); - - test('length', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.length(), testFile.size); - }); - - test('openRead', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.openRead().first, testFileBytes); - }); - - test('openRead with partial data', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.openRead(2, 5).first, testFileBytes.sublist(2, 5)); - }); - - test('readAsBytes', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.readAsBytes(), testFileBytes); - }); - - test('readAsString', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.readAsString(), testFileStringContents); - }); - - test('exists', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.exists(), true); - }); - - test('name', () async { - final file = PlatformScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile), - ); - - expect(await file.name(), testFile.name); - }); - }); - - group('download', () { - const crossFileDomElementId = '__x_file_dom_element'; - - group('XFile download', () { - test('creates a DOM container', () async { - final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; - final testOverrides = XFileTestOverrides(createAnchorElement: (_, _) => mockAnchor); - - final file = WebScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), - ); - - await file.download(); - - final html.Element? container = html.document.querySelector('#$crossFileDomElementId'); - - expect(container, isNotNull); - }); - - test('create anchor element', () async { - final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; - late final String setHref; - late final String? setDownload; - final testOverrides = XFileTestOverrides( - createAnchorElement: (String href, String? suggestedName) { - setHref = href; - setDownload = suggestedName; - return mockAnchor; - }, - ); - - final file = WebScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), - ); - - await file.download('path'); - - final html.Element container = html.document.querySelector('#$crossFileDomElementId')!; - - // Find anchor element. - late final html.HTMLAnchorElement element; - for (var i = 0; i < container.childNodes.length; i++) { - element = container.children.item(i)! as html.HTMLAnchorElement; - } - - // If element is not found, the `firstWhere` call will throw StateError. - expect(element, mockAnchor); - expect(element.tagName, 'A'); - expect(setHref, file.params.uri); - expect(setDownload, 'path'); - }); - - test('anchor element is clicked', () async { - final mockAnchor = html.document.createElement('a') as html.HTMLAnchorElement; - - final testOverrides = XFileTestOverrides(createAnchorElement: (_, _) => mockAnchor); - - final file = WebScopedStorageXFile( - WebScopedStorageXFileCreationParams.fromBlob(testFile, testOverrides: testOverrides), - ); - - var clicked = false; - mockAnchor.onClick.listen((html.MouseEvent event) => clicked = true); - - await file.download('path'); - - expect(clicked, true); - }); - }); - }); - }); -} From d37cb36a4f915506de0873fb0d0dac893c3569dc Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 24 Jun 2026 18:42:03 -0400 Subject: [PATCH 327/398] add test for range filter --- .../lib/src/byte_range_filter.dart | 63 +++++++++++++++++++ .../src/darwin_scoped_storage_cross_file.dart | 37 ++--------- .../test/byte_range_filter_test.dart | 39 ++++++++++++ 3 files changed, 108 insertions(+), 31 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart create mode 100644 packages/cross_file/cross_file_darwin/test/byte_range_filter_test.dart diff --git a/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart b/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart new file mode 100644 index 000000000000..95dc7082eb5b --- /dev/null +++ b/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart @@ -0,0 +1,63 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:math'; +import 'dart:typed_data'; + +/// Byte range filter for a continuous stream of data. +/// +/// Takes incoming chunks of bytes (Uint8List) as they arrive, and slices out +/// only the portion that falls within a specific ([start], [end]) index range. +/// +/// All byte chunks are passed to [addBytes] which returns only the bytes that +/// are within the desired range. +class ByteRangeFilter { + /// Constructs a [ByteRangeFilter]. + ByteRangeFilter({required this.start, this.end}) + : assert(start >= 0), + assert(end == null || end >= start); + + /// Starting index, inclusive. + final int start; + + /// End index, exclusive. + final int? end; + + int _currentByteIndex = 0; + + /// Adds a chunk of bytes to be filtered. + /// + /// Returns a list of bytes if they are within the desired range of [start] + /// and [end]. Otherwise, returns an empty list. + Uint8List addBytes(Uint8List bytes) { + Uint8List? inRangeBytes; + final int newByteIndex = _currentByteIndex + bytes.length; + + if (end == null) { + if (_currentByteIndex >= start) { + inRangeBytes = bytes; + } else { + if (newByteIndex > start) { + inRangeBytes = bytes.sublist(start - _currentByteIndex); + } + } + } else if (end case final int end) { + final int bytesLeftToRead = end - max(_currentByteIndex, start); + + if (bytesLeftToRead > 0) { + if (_currentByteIndex >= start) { + inRangeBytes = bytes.sublist(0, min(bytesLeftToRead, bytes.length)); + } else if (newByteIndex > start) { + inRangeBytes = bytes.sublist( + start - _currentByteIndex, + min(start - _currentByteIndex + bytesLeftToRead, bytes.length), + ); + } + } + } + + _currentByteIndex = newByteIndex; + return inRangeBytes ?? Uint8List(0); + } +} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index f778083c471a..73c26718edb5 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:ffi'; import 'dart:io'; -import 'dart:math'; import 'dart:ui'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -14,6 +13,7 @@ import 'package:flutter/foundation.dart'; import 'package:objective_c/objective_c.dart'; import 'package:path/path.dart' as path; +import 'byte_range_filter.dart'; import 'ffi_bindings.g.dart'; import 'security_scoped_resource.dart'; @@ -204,6 +204,8 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final streamController = StreamController(); + final filter = ByteRangeFilter(start: 0, end: end); + final PHAssetResource? resource = _tryGetAssetResource(identifier: params.uri); if (resource == null) { streamController.addError( @@ -213,41 +215,14 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile return streamController.stream; } - var currentByteIndex = 0; - void dataReceivedHandler(NSData data) { final Uint8List bytes = _extractBytesToUint8List(data); runOnPlatformThread(() { - final int newByteIndex = currentByteIndex + bytes.length; - final int startOrZero = start ?? 0; - - if (end == null) { - if (currentByteIndex >= startOrZero) { - streamController.add(bytes); - } else { - if (newByteIndex > startOrZero) { - streamController.add(bytes.sublist(startOrZero - currentByteIndex)); - } - } - } else { - final int bytesLeftToRead = end - max(currentByteIndex, startOrZero); - - if (bytesLeftToRead > 0) { - if (currentByteIndex >= startOrZero) { - streamController.add(bytes.sublist(0, min(bytesLeftToRead, bytes.length))); - } else if (newByteIndex > startOrZero) { - streamController.add( - bytes.sublist( - startOrZero - currentByteIndex, - min(startOrZero - currentByteIndex + bytesLeftToRead, bytes.length), - ), - ); - } - } + final Uint8List inRangeBytes = filter.addBytes(bytes); + if (inRangeBytes.isNotEmpty) { + streamController.add(inRangeBytes); } - - currentByteIndex = newByteIndex; }); } diff --git a/packages/cross_file/cross_file_darwin/test/byte_range_filter_test.dart b/packages/cross_file/cross_file_darwin/test/byte_range_filter_test.dart new file mode 100644 index 000000000000..73b3b8501720 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/byte_range_filter_test.dart @@ -0,0 +1,39 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:cross_file_darwin/src/byte_range_filter.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('ByteRangeFilter', () { + test('correctly reads all bytes with 0 start and null end', () async { + final filter = ByteRangeFilter(start: 0); + + final bytes = Uint8List.fromList([1, 2, 3]); + expect(filter.addBytes(bytes), bytes); + }); + + test('correctly reads desired sublist', () async { + final bytes = Uint8List.fromList([0, 1, 2, 3, 4]); + final filter = ByteRangeFilter(start: 1, end: 4); + + // Ignore byte before desired sublist. + expect(filter.addBytes(subListFromIndex(bytes, 0)), isEmpty); + // Read byte at start of desired sublist. + expect(filter.addBytes(subListFromIndex(bytes, 1)), subListFromIndex(bytes, 1)); + // Read byte between start and end of desired sublist. + expect(filter.addBytes(subListFromIndex(bytes, 2)), subListFromIndex(bytes, 2)); + // Read byte at end of desire sublist. + expect(filter.addBytes(subListFromIndex(bytes, 3)), subListFromIndex(bytes, 3)); + // Ignore byte after desired sublist. + expect(filter.addBytes(subListFromIndex(bytes, 4)), isEmpty); + }); + }); +} + +Uint8List subListFromIndex(Uint8List list, int index) { + return list.sublist(index, index + 1); +} From a639f7103b1804562a715fd396cc16d492fdc57f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:27:45 -0400 Subject: [PATCH 328/398] TODO for cross_file example --- packages/cross_file/cross_file/example/pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index 1a6cba1cd7e3..affcd86334e1 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -56,6 +56,9 @@ flutter: - assets/hello.txt dependency_overrides: + # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because + # the updated file_selector branch depends on cross_file from git and this overrides its + # dependency. cross_file: # When depending on this package from a real application you should use: # cross_file: ^x.y.z From dadac8b814edbb0dc01195aa2119e9bc81c9fa3a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:31:30 -0400 Subject: [PATCH 329/398] update uri docs --- packages/cross_file/cross_file/lib/src/cross_entity.dart | 2 +- .../lib/src/platform_cross_entity.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_entity.dart b/packages/cross_file/cross_file/lib/src/cross_entity.dart index 7eb04fcd4364..5d4a8d1223a3 100644 --- a/packages/cross_file/cross_file/lib/src/cross_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_entity.dart @@ -17,7 +17,7 @@ base class XEntity { @internal final PlatformXEntity platform; - /// A string used to reference the resource's location. + /// A unique string used to identify the resource. String get uri => platform.params.uri; /// Whether the resource represented by this reference exists. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart index 1be3386741f5..b98db1fc9140 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart @@ -11,7 +11,7 @@ abstract base class PlatformXEntityCreationParams { /// Constructs a [PlatformXEntityCreationParams]. const PlatformXEntityCreationParams({required this.uri}); - /// A string used to reference the resource's location. + /// A unique string used to identify the resource. final String uri; } From b43a6f4a223fb58df548360df1d8cf201a0b837c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 15:40:59 -0400 Subject: [PATCH 330/398] change to just getextension --- .../cross_file/cross_file/lib/src/cross_directory.dart | 10 +--------- packages/cross_file/cross_file/lib/src/cross_file.dart | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 67b81992b15d..e5a965819293 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -80,18 +80,10 @@ base class XDirectory extends XEntity { @override PlatformXDirectory get platform => super.platform as PlatformXDirectory; - /// Provides a nonnull platform class extension. - /// - /// Will throw an exception if the specified platform extension can not be - /// returned. - S getExtension() { - return platform.extension! as S; - } - /// Attempt to provide the platform class extension. /// /// Returns null if the specified platform extension cannot be retrieved. - S? maybeGetExtension() { + S? getExtension() { return platform.extension is S ? platform.extension! as S : null; } diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 84b791c684a9..a9043cb5c997 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -74,18 +74,10 @@ base class XFile extends XEntity { @override PlatformXFile get platform => super.platform as PlatformXFile; - /// Provides a nonnull platform class extension. - /// - /// Will throw an exception if the specified platform extension can not be - /// returned. - S getExtension() { - return platform.extension! as S; - } - /// Attempt to provide the platform class extension. /// /// Returns null if the specified platform extension cannot be retrieved. - S? maybeGetExtension() { + S? getExtension() { return platform.extension is S ? platform.extension! as S : null; } From d4835577d9e367a807fa6aa69e1d84721c9d0d19 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:16:21 -0400 Subject: [PATCH 331/398] change to entity as base --- packages/cross_file/cross_file/README.md | 4 ++-- .../example/integration_test/cross_file_test.dart | 2 +- .../cross_file/cross_file/example/lib/readme_excerpts.dart | 4 ++-- .../cross_file/cross_file/lib/src/cross_directory.dart | 7 ------- packages/cross_file/cross_file/lib/src/cross_entity.dart | 7 +++++++ packages/cross_file/cross_file/lib/src/cross_file.dart | 7 ------- 6 files changed, 12 insertions(+), 19 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index 08900b648ad9..fd67227b8423 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -87,13 +87,13 @@ if (CrossFileWeb.isCurrentImplementation()) { } await file - .maybeGetExtension() + .getExtension() ?.startAccessingSecurityScopedResource(); debugPrint(await file.readAsString()); await file - .maybeGetExtension() + .getExtension() ?.stopAccessingSecurityScopedResource(); ``` diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart index c20b611a38e7..1093c380cd81 100644 --- a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -22,7 +22,7 @@ void main() { expect(await xDir.exists(), isTrue); final file = XFile.fromPath(path.join(dir.path, 'hello.txt')); - file.getExtension().file + file.getExtension()!.file ..createSync() ..writeAsStringSync('Hello, World!'); diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 9d68935cd960..42aa7bc5bb70 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -46,13 +46,13 @@ Future accessPlatformFeatures() async { } await file - .maybeGetExtension() + .getExtension() ?.startAccessingSecurityScopedResource(); debugPrint(await file.readAsString()); await file - .maybeGetExtension() + .getExtension() ?.stopAccessingSecurityScopedResource(); // #enddocregion platform_features diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index e5a965819293..67024b9c1b41 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -80,13 +80,6 @@ base class XDirectory extends XEntity { @override PlatformXDirectory get platform => super.platform as PlatformXDirectory; - /// Attempt to provide the platform class extension. - /// - /// Returns null if the specified platform extension cannot be retrieved. - S? getExtension() { - return platform.extension is S ? platform.extension! as S : null; - } - /// Lists the sub-directories and files of this directory. Stream list() { // Converts PlatformXEntities to XEntities. diff --git a/packages/cross_file/cross_file/lib/src/cross_entity.dart b/packages/cross_file/cross_file/lib/src/cross_entity.dart index 5d4a8d1223a3..0d0bf532d91e 100644 --- a/packages/cross_file/cross_file/lib/src/cross_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_entity.dart @@ -17,6 +17,13 @@ base class XEntity { @internal final PlatformXEntity platform; + /// Attempt to provide the platform class extension. + /// + /// Returns null if the specified platform extension cannot be retrieved. + S? getExtension() { + return platform.extension is S ? platform.extension! as S : null; + } + /// A unique string used to identify the resource. String get uri => platform.params.uri; diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index a9043cb5c997..c29e13ec5e9f 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -74,13 +74,6 @@ base class XFile extends XEntity { @override PlatformXFile get platform => super.platform as PlatformXFile; - /// Attempt to provide the platform class extension. - /// - /// Returns null if the specified platform extension cannot be retrieved. - S? getExtension() { - return platform.extension is S ? platform.extension! as S : null; - } - /// Date and time when the resource was last modified, if the information is /// available. Future lastModified() => platform.lastModified(); From 70c305835ae87faf1cd1bbec2637e5cd7bb93414 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:18:38 -0400 Subject: [PATCH 332/398] dot comments encoding --- packages/cross_file/cross_file/lib/src/cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index c29e13ec5e9f..4f6dbd055c83 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -101,7 +101,7 @@ base class XFile extends XEntity { /// the resource. Future readAsBytes() => platform.readAsBytes(); - /// Reads the entire resource contents as a string using the given Encoding. + /// Reads the entire resource contents as a string using the given [Encoding]. /// /// Platforms may throw an exception if there is an error opening or reading /// the resource. From faa0a1a4c92c16aa2b251bcb6a874d6d1da96da3 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:26:55 -0400 Subject: [PATCH 333/398] update name docs --- packages/cross_file/cross_file/lib/src/cross_file.dart | 3 ++- .../lib/src/platform_cross_file.dart | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 4f6dbd055c83..97846c056646 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -108,7 +108,8 @@ base class XFile extends XEntity { Future readAsString({Encoding encoding = utf8}) => platform.readAsString(encoding: encoding); - /// The name of the resource represented by this object. + /// The name of the resource represented by this object or null if the file + /// doesn't exist or information is not available. /// /// The path is excluded from this value. Future name() => platform.name(); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 5961dff151c4..ec3ad2eae6f8 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -128,10 +128,9 @@ abstract base class PlatformXFile extends PlatformXEntity { /// the resource. Future readAsString({Encoding encoding = utf8}); - /// The name of the resource represented by this object. + /// The name of the resource represented by this object or null if the file + /// doesn't exist or information is not available. /// /// The path is excluded from this value. - /// - /// Returns null if file doesn't exist or information is not available. Future name(); } From 063d7763f68b726f7848ea4287e791a8723d5770 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:28:39 -0400 Subject: [PATCH 334/398] name docs clarification path --- packages/cross_file/cross_file/lib/src/cross_file.dart | 3 ++- .../lib/src/platform_cross_file.dart | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 97846c056646..ec3cfb0230f9 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -111,6 +111,7 @@ base class XFile extends XEntity { /// The name of the resource represented by this object or null if the file /// doesn't exist or information is not available. /// - /// The path is excluded from this value. + /// If the file is identified by a path, only the base name of the file will + /// gbe included in the name. Future name() => platform.name(); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index ec3ad2eae6f8..486fcc742110 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -131,6 +131,7 @@ abstract base class PlatformXFile extends PlatformXEntity { /// The name of the resource represented by this object or null if the file /// doesn't exist or information is not available. /// - /// The path is excluded from this value. + /// If the file is identified by a path, only the base name of the file will + /// be included in the name. Future name(); } From 4bea365ab6805a6f702e9a03c8473c5b042a7b4e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:35:16 -0400 Subject: [PATCH 335/398] undo webview change --- .../example/macos/Runner.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj index 858185a5ce46..115f5c2b3249 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/macos/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 54; + objectVersion = 60; objects = { /* Begin PBXAggregateTarget section */ From e8d9d375408a3b0cfc37cbeaf2d97ec4f9f57368 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:43:46 -0400 Subject: [PATCH 336/398] fix dependabot location --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 43f6164db2c2..0cba0bb92993 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -30,7 +30,6 @@ updates: - /packages/camera/camera_android_camerax/example/android/app - /packages/camera/camera/example/android/app - /packages/cross_file/cross_file/example/android/app - - /packages/cross_file/cross_file_android/android - /packages/cross_file/cross_file_android/example/android/app - /packages/espresso/example/android/app - /packages/extension_google_sign_in_as_googleapis_auth/example/android/app @@ -87,6 +86,7 @@ updates: directories: - /packages/camera/camera_android/android - /packages/camera/camera_android_camerax/android + - /packages/cross_file/cross_file_android/android - /packages/espresso/android - /packages/file_selector/file_selector_android/android - /packages/flutter_plugin_android_lifecycle/android From 568e468987f9acb219590633b0980f361d41a513 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:50:40 -0400 Subject: [PATCH 337/398] update platform specific in platform interface --- .../lib/src/platform_cross_directory.dart | 6 +++--- .../lib/src/platform_cross_entity.dart | 2 +- .../lib/src/platform_cross_file.dart | 6 +++--- .../platform_scoped_storage_cross_directory.dart | 6 +++--- .../scoped_storage/platform_scoped_storage_cross_file.dart | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 86c2869025f1..03182a2a19d5 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -11,11 +11,11 @@ import 'platform_cross_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXDirectory]. /// -/// Platform specific implementations can add additional fields by extending +/// Platform-specific implementations can add additional fields by extending /// this class. /// /// This example demonstrates how to extend the [PlatformXDirectoryCreationParams] to -/// provide additional platform specific parameters. +/// provide additional platform-specific parameters. /// /// When extending [PlatformXDirectoryCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking @@ -45,7 +45,7 @@ base class PlatformXDirectoryCreationParams extends PlatformXEntityCreationParam const PlatformXDirectoryCreationParams({required super.uri}); } -/// Base mixin used to provide platform specific features for implementations of +/// Base mixin used to provide platform-specific features for implementations of /// [PlatformXDirectory]. /// /// Platform implementations are expected to declare a mixin that implements diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart index b98db1fc9140..e573e010f3a0 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart @@ -27,7 +27,7 @@ abstract base class PlatformXEntity { /// The parameters used to initialize the [PlatformXEntity]. final PlatformXEntityCreationParams params; - /// Extension for providing platform specific features. + /// Extension for providing platform-specific features. PlatformXEntityExtension? get extension => null; /// Whether the resource represented by this reference exists. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 486fcc742110..9966a6ce8ae4 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -12,11 +12,11 @@ import 'platform_cross_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXFile]. /// -/// Platform specific implementations can add additional fields by extending +/// Platform-specific implementations can add additional fields by extending /// this class. /// /// This example demonstrates how to extend the [PlatformXFileCreationParams] to -/// provide additional platform specific parameters. +/// provide additional platform-specific parameters. /// /// When extending [PlatformXFileCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking @@ -46,7 +46,7 @@ base class PlatformXFileCreationParams extends PlatformXEntityCreationParams { const PlatformXFileCreationParams({required super.uri}); } -/// Base mixin used to provide platform specific features for implementations of +/// Base mixin used to provide platform-specific features for implementations of /// [PlatformXFile]. /// /// Platform implementations are expected to declare a mixin that implements diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index e1f403b65661..3511015d4a97 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -9,11 +9,11 @@ import '../platform_cross_directory.dart'; /// Object specifying creation parameters for creating a [PlatformScopedStorageXDirectory]. /// -/// Platform specific implementations can add additional fields by extending +/// Platform-specific implementations can add additional fields by extending /// this class. /// /// This example demonstrates how to extend the [PlatformScopedStorageXDirectoryCreationParams] to -/// provide additional platform specific parameters. +/// provide additional platform-specific parameters. /// /// When extending [PlatformScopedStorageXDirectoryCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking @@ -43,7 +43,7 @@ base class PlatformScopedStorageXDirectoryCreationParams extends PlatformXDirect const PlatformScopedStorageXDirectoryCreationParams({required super.uri}); } -/// Base mixin used to provide platform specific features for implementations of +/// Base mixin used to provide platform-specific features for implementations of /// [PlatformScopedStorageXDirectory]. /// /// Platform implementations are expected to declare a mixin that implements diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index a01efac9a3ca..442f8cc2bccc 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -9,11 +9,11 @@ import '../platform_cross_file.dart'; /// Object specifying creation parameters for creating a [PlatformScopedStorageXFile]. /// -/// Platform specific implementations can add additional fields by extending +/// Platform-specific implementations can add additional fields by extending /// this class. /// /// This example demonstrates how to extend the [PlatformScopedStorageXFileCreationParams] to -/// provide additional platform specific parameters. +/// provide additional platform-specific parameters. /// /// When extending [PlatformScopedStorageXFileCreationParams] additional parameters /// should always accept `null` or have a default value to prevent breaking @@ -43,7 +43,7 @@ base class PlatformScopedStorageXFileCreationParams extends PlatformXFileCreatio const PlatformScopedStorageXFileCreationParams({required super.uri}); } -/// Base mixin used to provide platform specific features for implementations of +/// Base mixin used to provide platform-specific features for implementations of /// [PlatformScopedStorageXFile]. /// /// Platform implementations are expected to declare a mixin that implements From 9bc0c6574baf1e40e8e3cff3695810043bd3e10e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 19:59:58 -0400 Subject: [PATCH 338/398] fix platform specific in other packages --- .../lib/src/darwin_scoped_storage_cross_directory.dart | 2 +- .../lib/src/darwin_scoped_storage_cross_file.dart | 4 ++-- .../cross_file/cross_file_io/lib/src/io_cross_directory.dart | 2 +- packages/cross_file/cross_file_io/lib/src/io_cross_file.dart | 2 +- .../cross_file_web/lib/src/web_scoped_storage_cross_file.dart | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 90723ce091e1..6146741f039c 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -121,7 +121,7 @@ base class SecurityScopedDarwinScopedStorageXDirectory extends DarwinScopedStora } } -/// Provides platform specific features for +/// Provides platform-specific features for /// [SecurityScopedDarwinScopedStorageXDirectory]. mixin SecurityScopedDarwinScopedStorageXDirectoryExtension implements PlatformScopedStorageXDirectoryExtension, SecurityScopedResource {} diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 73c26718edb5..68fe3d4c813a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -335,11 +335,11 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } } -/// Provides platform specific features for +/// Provides platform-specific features for /// [SecurityScopedDarwinScopedStorageXFile]. mixin SecurityScopedDarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension, SecurityScopedResource {} -/// Provides platform specific features for +/// Provides platform-specific features for /// [PhotoKitDarwinScopedStorageXFile]. mixin PhotoKitDarwinScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension {} diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart index a529a13197a2..bdb97c89e522 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -60,7 +60,7 @@ base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { } } -/// Provides platform specific features for [IOXDirectory]. +/// Provides platform-specific features for [IOXDirectory]. mixin IOXDirectoryExtension implements PlatformXDirectoryExtension { /// The underlying directory. Directory get directory; diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index 9d844e474e8c..b0e0cc56174b 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -78,7 +78,7 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { Future name() async => path.basename(file.path); } -/// Provides platform specific features for [IOXFile]. +/// Provides platform-specific features for [IOXFile]. mixin IOXFileExtension implements PlatformXFileExtension { /// The underlying file. File get file; diff --git a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart index cdb35dd6d7b8..c7c5e60e959e 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart @@ -173,7 +173,7 @@ base class WebScopedStorageXFile extends PlatformScopedStorageXFile } } -/// Provides platform specific features for [WebScopedStorageXFile]. +/// Provides platform-specific features for [WebScopedStorageXFile]. mixin WebScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension { /// The raw data represented by a [WebScopedStorageXFile]. Future getBlob(); From c398f3fb1f9fbab37c41f65f531d50c2e4dc3b63 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:08:25 -0400 Subject: [PATCH 339/398] change to make extension sound optional --- .../lib/src/platform_cross_directory.dart | 9 +++++---- .../lib/src/platform_cross_file.dart | 5 +++-- .../platform_scoped_storage_cross_directory.dart | 9 +++++---- .../platform_scoped_storage_cross_file.dart | 9 +++++---- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 03182a2a19d5..191385290870 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -48,11 +48,12 @@ base class PlatformXDirectoryCreationParams extends PlatformXEntityCreationParam /// Base mixin used to provide platform-specific features for implementations of /// [PlatformXDirectory]. /// -/// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformXDirectory.extension]. +/// When providing platform specific features, platform implementations are +/// expected to declare a mixin that implements this mixin and return an +/// instance with [PlatformXDirectory.extension]. /// /// ```dart -/// base class AndroidXDirectory extends PlatformXDirectory with AndroidXFileExtension { +/// base class AndroidXDirectory extends PlatformXDirectory with AndroidXDirectoryExtension { /// // ... /// @override /// PlatformXDirectoryExtension? get extension => this; @@ -62,7 +63,7 @@ base class PlatformXDirectoryCreationParams extends PlatformXEntityCreationParam /// } /// } /// -/// mixin AndroidXFileExtension implements PlatformXDirectoryExtension { +/// mixin AndroidXDirectoryExtension implements PlatformXDirectoryExtension { /// Future platformMethod(); /// } /// ``` diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 9966a6ce8ae4..02de71daf8e7 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -49,8 +49,9 @@ base class PlatformXFileCreationParams extends PlatformXEntityCreationParams { /// Base mixin used to provide platform-specific features for implementations of /// [PlatformXFile]. /// -/// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformXFile.extension]. +/// When providing platform specific features, platform implementations are +/// expected to declare a mixin that implements this mixin and return an +/// instance with [PlatformXFile.extension]. /// /// ```dart /// base class AndroidXFile extends PlatformXFile with AndroidXFileExtension { diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index 3511015d4a97..da670110427b 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -46,11 +46,12 @@ base class PlatformScopedStorageXDirectoryCreationParams extends PlatformXDirect /// Base mixin used to provide platform-specific features for implementations of /// [PlatformScopedStorageXDirectory]. /// -/// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformScopedStorageXDirectory.extension]. +/// When providing platform specific features, platform implementations are +/// expected to declare a mixin that implements this mixin and return an +/// instance with [PlatformScopedStorageXDirectory.extension]. /// /// ```dart -/// base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirectory with AndroidXFileExtension { +/// base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirectory with AndroidScopedStorageXDirectoryExtension { /// // ... /// @override /// PlatformScopedStorageXDirectoryExtension? get extension => this; @@ -60,7 +61,7 @@ base class PlatformScopedStorageXDirectoryCreationParams extends PlatformXDirect /// } /// } /// -/// mixin AndroidXFileExtension implements PlatformScopedStorageXDirectoryExtension { +/// mixin AndroidScopedStorageXDirectoryExtension implements PlatformScopedStorageXDirectoryExtension { /// Future platformMethod(); /// } /// ``` diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index 442f8cc2bccc..29b37f375615 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -46,11 +46,12 @@ base class PlatformScopedStorageXFileCreationParams extends PlatformXFileCreatio /// Base mixin used to provide platform-specific features for implementations of /// [PlatformScopedStorageXFile]. /// -/// Platform implementations are expected to declare a mixin that implements -/// this mixin and return an instance with [PlatformScopedStorageXFile.extension]. +/// When providing platform specific features, platform implementations are +/// expected to declare a mixin that implements this mixin and return an +/// instance with [PlatformScopedStorageXFile.extension]. /// /// ```dart -/// base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile with AndroidXFileExtension { +/// base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile with AndroidScopedStorageXFileExtension { /// // ... /// @override /// PlatformScopedStorageXFileExtension? get extension => this; @@ -60,7 +61,7 @@ base class PlatformScopedStorageXFileCreationParams extends PlatformXFileCreatio /// } /// } /// -/// mixin AndroidXFileExtension implements PlatformScopedStorageXFileExtension { +/// mixin AndroidScopedStorageXFileExtension implements PlatformScopedStorageXFileExtension { /// Future platformMethod(); /// } /// ``` From 0db1cb4feda3ca4011a447e1cc7c98ecb1ae5160 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:20:11 -0400 Subject: [PATCH 340/398] update can read for directories --- .../cross_file/lib/src/scoped_storage_cross_directory.dart | 3 ++- .../platform_scoped_storage_cross_directory.dart | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index 6d571cd74ef9..214bba509443 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -79,6 +79,7 @@ base class ScopedStorageXDirectory extends XDirectory { @override PlatformScopedStorageXDirectory get platform => super.platform as PlatformScopedStorageXDirectory; - /// Whether the directory represented by this reference can be read. + /// Whether the files in this directory represented by this reference can be + /// viewed. Future canRead() => platform.canRead(); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index da670110427b..d7c45f21a4cb 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -95,6 +95,7 @@ abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { PlatformScopedStorageXDirectoryCreationParams get params => super.params as PlatformScopedStorageXDirectoryCreationParams; - /// Whether the directory represented by this reference can be read. + /// Whether the files in this directory represented by this reference can be + /// viewed. Future canRead(); } From 6dbe663c076f65481a2a404777bc9fca0e8b70e0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 30 Jul 2026 20:35:59 -0400 Subject: [PATCH 341/398] set to version 1.0 --- packages/cross_file/cross_file_android/pubspec.yaml | 2 +- packages/cross_file/cross_file_darwin/pubspec.yaml | 2 +- packages/cross_file/cross_file_io/pubspec.yaml | 2 +- packages/cross_file/cross_file_platform_interface/pubspec.yaml | 2 +- packages/cross_file/cross_file_web/pubspec.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 6eefc3dc80a9..26d3933a696d 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_android description: Implementation of cross_file_platform_interface for Android. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.1.0 +version: 1.0.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 378a6f9c6f12..fcf7b2e48660 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_darwin description: Implementation of cross_file_platform_interface for iOS and macOS. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_darwin issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.1.0 +version: 1.0.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index a3be39e13e97..f4626e867b50 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_io description: Implementation of cross_file_platform_interface for dart:io. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_io issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.1.0 +version: 1.0.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_platform_interface/pubspec.yaml b/packages/cross_file/cross_file_platform_interface/pubspec.yaml index dacb6c7ca3d2..58ecfd9b7a73 100644 --- a/packages/cross_file/cross_file_platform_interface/pubspec.yaml +++ b/packages/cross_file/cross_file_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cr issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 # 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: 0.1.0 +version: 1.0.0 publish_to: none environment: diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index 0ead2be5996b..eb64bf911e8e 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -2,7 +2,7 @@ name: cross_file_web description: Implementation of cross_file_platform_interface for web. repository: https://github.com/flutter/packages/tree/main/packages/cross_file/cross_file_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+cross_file%22 -version: 0.1.0 +version: 1.0.0 publish_to: none environment: From 78ea879dbee4dce7b390cc2c1f70f156a0ad2958 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 31 Jul 2026 13:55:18 -0400 Subject: [PATCH 342/398] extra newliine --- packages/cross_file/cross_file/test/test_stubs.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 28116ffd3af0..9528dd1f24e1 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:convert'; - import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; From d3ee6efed163bb8c904da27f9327a032a0c8946f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:04:32 -0400 Subject: [PATCH 343/398] you can find --- packages/cross_file/cross_file/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index fd67227b8423..e879d3b1f1cf 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -14,8 +14,7 @@ A Flutter plugin that manages files and interactions with file dialogs. ## Usage -Import `package:cross_file/cross_file.dart`, instantiate a `XFile` -using a path or byte array and use its methods and properties to +Instantiate a `XFile` using a uri or path and use its methods and properties to access the file and its metadata. Example: @@ -34,7 +33,7 @@ if (await file.exists()) { } ``` -You will find links to the API docs on the [pub page](https://pub.dev/packages/cross_file). +You can find links to the API docs on the [pub page](https://pub.dev/packages/cross_file). ### Implementation-Specific Features From 0415b2e09e7a3a063db744a16d6b314e6138a991 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:20:31 -0400 Subject: [PATCH 344/398] update gradle for android to compile --- .../cross_file_android/android/build.gradle.kts | 5 +---- .../example/android/app/build.gradle.kts | 11 ++++++----- .../example/android/build.gradle.kts | 6 +++--- .../example/android/gradle.properties | 7 ++++++- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- .../example/android/settings.gradle.kts | 4 ++-- 6 files changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/build.gradle.kts b/packages/cross_file/cross_file_android/android/build.gradle.kts index 5782a2a65844..d7ee846b8687 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle.kts +++ b/packages/cross_file/cross_file_android/android/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - group = "dev.flutter.packages.cross_file_android" version = "1.0" @@ -25,12 +23,11 @@ allprojects { plugins { id("com.android.library") - id("kotlin-android") } kotlin { compilerOptions { - jvmTarget = JvmTarget.fromTarget(JavaVersion.VERSION_17.toString()) + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 } } diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts index a08966429556..6b24ae71faea 100644 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -1,6 +1,5 @@ plugins { id("com.android.application") - id("kotlin-android") id("dev.flutter.flutter-gradle-plugin") } @@ -14,10 +13,6 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - defaultConfig { applicationId = "dev.flutter.packages.cross_file_android_example" minSdk = flutter.minSdkVersion @@ -37,6 +32,12 @@ android { } } +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + flutter { source = "../.." } diff --git a/packages/cross_file/cross_file_android/example/android/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/build.gradle.kts index ec52edfd8d36..7926609a65e8 100644 --- a/packages/cross_file/cross_file_android/example/android/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/build.gradle.kts @@ -15,9 +15,9 @@ allprojects { } val newBuildDir: Directory = - rootProject.layout.buildDirectory - .dir("../../build") - .get() + rootProject.layout.buildDirectory + .dir("../../build") + .get() rootProject.layout.buildDirectory.value(newBuildDir) subprojects { diff --git a/packages/cross_file/cross_file_android/example/android/gradle.properties b/packages/cross_file/cross_file_android/example/android/gradle.properties index fbee1d8cdafc..6146589810a7 100644 --- a/packages/cross_file/cross_file_android/example/android/gradle.properties +++ b/packages/cross_file/cross_file_android/example/android/gradle.properties @@ -1,2 +1,7 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx4G android.useAndroidX=true + +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties index 02767eb1ca47..a20f2c46d22e 100644 --- a/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/cross_file/cross_file_android/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip diff --git a/packages/cross_file/cross_file_android/example/android/settings.gradle.kts b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts index a0118892641d..575dbbe6c4c6 100644 --- a/packages/cross_file/cross_file_android/example/android/settings.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/settings.gradle.kts @@ -20,8 +20,8 @@ pluginManagement { // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false + id("com.android.application") version "9.1.0" apply false + id("org.jetbrains.kotlin.android") version "2.4.0" apply false id("com.google.cloud.artifactregistry.gradle-plugin") version "2.2.1" } From e11124eebb7f241201833de5e82fc675ab13e634 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:34:11 -0400 Subject: [PATCH 345/398] android compiles with new kotlin names --- .../cross_file_android/android/build.gradle.kts | 4 ++-- .../cross_file_android/android/lint-baseline.xml | 10 +++++----- .../android/src/main/AndroidManifest.xml | 2 +- .../CrossFileAndroidPlugin.kt | 2 +- .../ProxyApiRegistrar.kt | 16 ++++++++-------- .../proxies/AndroidLibrary.g.kt | 2 +- .../proxies/ContentResolverProxyApi.kt | 4 ++-- .../proxies/DocumentFileProxyApi.kt | 4 ++-- .../proxies/InputStreamProxyApi.kt | 4 ++-- .../TestProxyApiRegistrar.kt | 2 +- .../proxies/ContentResolverTest.kt | 2 +- .../proxies/DocumentFileTest.kt | 2 +- .../proxies/InputStreamTest.kt | 2 +- .../example/android/app/build.gradle.kts | 4 ++-- .../MainActivityTest.kt | 2 +- .../android/app/src/debug/AndroidManifest.xml | 2 +- .../DriverExtensionActivity.kt | 2 +- .../MainActivity.kt | 2 +- .../pigeons/android_library.dart | 4 ++-- .../cross_file/cross_file_android/pubspec.yaml | 2 +- 20 files changed, 37 insertions(+), 37 deletions(-) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/CrossFileAndroidPlugin.kt (94%) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/ProxyApiRegistrar.kt (59%) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/AndroidLibrary.g.kt (99%) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/ContentResolverProxyApi.kt (87%) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/DocumentFileProxyApi.kt (94%) rename packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/InputStreamProxyApi.kt (89%) rename packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/TestProxyApiRegistrar.kt (83%) rename packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/ContentResolverTest.kt (95%) rename packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/DocumentFileTest.kt (98%) rename packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/{cross_file_android => crossfileandroid}/proxies/InputStreamTest.kt (96%) rename packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/{cross_file_android_example => crossfileandroidexample}/MainActivityTest.kt (90%) rename packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/{cross_file_android_example => crossfileandroidexample}/DriverExtensionActivity.kt (85%) rename packages/cross_file/cross_file_android/example/android/app/src/main/kotlin/dev/flutter/packages/{cross_file_android_example => crossfileandroidexample}/MainActivity.kt (80%) diff --git a/packages/cross_file/cross_file_android/android/build.gradle.kts b/packages/cross_file/cross_file_android/android/build.gradle.kts index d7ee846b8687..000047c9636c 100644 --- a/packages/cross_file/cross_file_android/android/build.gradle.kts +++ b/packages/cross_file/cross_file_android/android/build.gradle.kts @@ -1,4 +1,4 @@ -group = "dev.flutter.packages.cross_file_android" +group = "dev.flutter.packages.crossfileandroid" version = "1.0" buildscript { @@ -32,7 +32,7 @@ kotlin { } android { - namespace = "dev.flutter.packages.cross_file_android" + namespace = "dev.flutter.packages.crossfileandroid" compileSdk = flutter.compileSdkVersion compileOptions { diff --git a/packages/cross_file/cross_file_android/android/lint-baseline.xml b/packages/cross_file/cross_file_android/android/lint-baseline.xml index 31b083d26319..b58b2ca900cd 100644 --- a/packages/cross_file/cross_file_android/android/lint-baseline.xml +++ b/packages/cross_file/cross_file_android/android/lint-baseline.xml @@ -7,7 +7,7 @@ errorLine1=" return strongInstances.remove(identifier) as T?" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -18,7 +18,7 @@ errorLine1=" return instance != null && identifiers.containsKey(IdentityWeakReference(instance))" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -29,7 +29,7 @@ errorLine1=" weakInstances.remove(identifier)" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -40,7 +40,7 @@ errorLine1=" strongInstances.remove(identifier)" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> @@ -51,7 +51,7 @@ errorLine1=" require(!weakInstances.containsKey(identifier)) {" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> diff --git a/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml b/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml index 5ac3f7b5b2af..46521c798a9f 100644 --- a/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml +++ b/packages/cross_file/cross_file_android/android/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ + package="dev.flutter.packages.crossfileandroid"> diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/CrossFileAndroidPlugin.kt similarity index 94% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/CrossFileAndroidPlugin.kt index 2c2a7dcdb419..889547c0280d 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/CrossFileAndroidPlugin.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/CrossFileAndroidPlugin.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android +package dev.flutter.packages.crossfileandroid import io.flutter.embedding.engine.plugins.FlutterPlugin diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/ProxyApiRegistrar.kt similarity index 59% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/ProxyApiRegistrar.kt index 65b52b1eff15..a99a3b88a2ef 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/ProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/ProxyApiRegistrar.kt @@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android +package dev.flutter.packages.crossfileandroid import android.content.Context -import dev.flutter.packages.cross_file_android.proxies.AndroidLibraryPigeonProxyApiRegistrar -import dev.flutter.packages.cross_file_android.proxies.ContentResolverProxyApi -import dev.flutter.packages.cross_file_android.proxies.DocumentFileProxyApi -import dev.flutter.packages.cross_file_android.proxies.InputStreamProxyApi -import dev.flutter.packages.cross_file_android.proxies.PigeonApiContentResolver -import dev.flutter.packages.cross_file_android.proxies.PigeonApiDocumentFile -import dev.flutter.packages.cross_file_android.proxies.PigeonApiInputStream +import dev.flutter.packages.crossfileandroid.proxies.AndroidLibraryPigeonProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.proxies.ContentResolverProxyApi +import dev.flutter.packages.crossfileandroid.proxies.DocumentFileProxyApi +import dev.flutter.packages.crossfileandroid.proxies.InputStreamProxyApi +import dev.flutter.packages.crossfileandroid.proxies.PigeonApiContentResolver +import dev.flutter.packages.crossfileandroid.proxies.PigeonApiDocumentFile +import dev.flutter.packages.crossfileandroid.proxies.PigeonApiInputStream import io.flutter.plugin.common.BinaryMessenger /** diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/AndroidLibrary.g.kt similarity index 99% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/AndroidLibrary.g.kt index 10b5175cc75e..bc75d6620ebf 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/AndroidLibrary.g.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/AndroidLibrary.g.kt @@ -5,7 +5,7 @@ // See also: https://pub.dev/packages/pigeon @file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies import android.util.Log import io.flutter.plugin.common.BasicMessageChannel diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverProxyApi.kt similarity index 87% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverProxyApi.kt index bd71a53188f2..1a1a68bab291 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverProxyApi.kt @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies import android.content.ContentResolver import androidx.core.net.toUri -import dev.flutter.packages.cross_file_android.ProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.ProxyApiRegistrar import java.io.InputStream /** diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileProxyApi.kt similarity index 94% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileProxyApi.kt index af781ce7bcc9..701ecd02104f 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileProxyApi.kt @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies import androidx.core.net.toUri import androidx.documentfile.provider.DocumentFile -import dev.flutter.packages.cross_file_android.ProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.ProxyApiRegistrar /** * ProxyApi implementation for [DocumentFile]. diff --git a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamProxyApi.kt similarity index 89% rename from packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt rename to packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamProxyApi.kt index 65cbe727fa28..719800ddcec9 100644 --- a/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamProxyApi.kt +++ b/packages/cross_file/cross_file_android/android/src/main/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamProxyApi.kt @@ -2,9 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies -import dev.flutter.packages.cross_file_android.ProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.ProxyApiRegistrar import java.io.InputStream /** diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/TestProxyApiRegistrar.kt similarity index 83% rename from packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt rename to packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/TestProxyApiRegistrar.kt index eea7e75059b1..7f6e97b39052 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/TestProxyApiRegistrar.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/TestProxyApiRegistrar.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android +package dev.flutter.packages.crossfileandroid import org.mockito.kotlin.mock diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt similarity index 95% rename from packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt rename to packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt index fe48009226ce..9a440ec717f8 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies import android.content.ContentResolver import android.net.Uri diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt similarity index 98% rename from packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt rename to packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt index fa6d193488d3..d08a6f2e5504 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies import android.net.Uri import androidx.documentfile.provider.DocumentFile diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt similarity index 96% rename from packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt rename to packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt index 9463f839cff2..11b7e2507f20 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/cross_file_android/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android.proxies +package dev.flutter.packages.crossfileandroid.proxies import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar import java.io.ByteArrayInputStream diff --git a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts index 6b24ae71faea..2825d5ae28de 100644 --- a/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file_android/example/android/app/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } android { - namespace = "dev.flutter.packages.cross_file_android_example" + namespace = "dev.flutter.packages.crossfileandroidexample" compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion @@ -14,7 +14,7 @@ android { } defaultConfig { - applicationId = "dev.flutter.packages.cross_file_android_example" + applicationId = "dev.flutter.packages.crossfileandroidexample" minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode diff --git a/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt b/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/crossfileandroidexample/MainActivityTest.kt similarity index 90% rename from packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt rename to packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/crossfileandroidexample/MainActivityTest.kt index a2e2b13340c6..2ff12804584b 100644 --- a/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_android_example/MainActivityTest.kt +++ b/packages/cross_file/cross_file_android/example/android/app/src/androidTest/kotlin/dev/flutter/packages/crossfileandroidexample/MainActivityTest.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_android_example +package dev.flutter.packages.crossfileandroidexample import androidx.test.rule.ActivityTestRule import dev.flutter.plugins.integration_test.FlutterTestRunner diff --git a/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml b/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml index 6601c9953612..d01390f0054c 100644 --- a/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/cross_file/cross_file_android/example/android/app/src/debug/AndroidManifest.xml @@ -6,7 +6,7 @@ Date: Fri, 31 Jul 2026 14:36:20 -0400 Subject: [PATCH 346/398] unused imports --- .../Sources/cross_file_darwin/CrossFileDarwinPlugin.swift | 2 -- .../example/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift index 9af279da47ca..c8084a8eec74 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift @@ -4,9 +4,7 @@ #if os(iOS) import Flutter - import UIKit #elseif os(macOS) - import Cocoa import FlutterMacOS #endif diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index 38eaae5d15d7..4cf36285736c 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -380,7 +380,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -508,7 +508,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -559,7 +559,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 13.0; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; From f5e8752da9570ca78e1bfa3e4114c0c9568b1746 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:52:15 -0400 Subject: [PATCH 347/398] update ffigen --- .../cross_file_darwin_objc/ffi_bindings.g.m | 176 ++++++++---------- .../macos/Runner.xcodeproj/project.pbxproj | 6 +- .../cross_file/cross_file_darwin/pubspec.yaml | 2 +- 3 files changed, 82 insertions(+), 102 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index fc7d39ee327a..8cc5eb341fa2 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -1,11 +1,7 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - +#include #import -#import #import -#include +#import #if !__has_feature(objc_arc) #error "This file must be compiled with ARC enabled" @@ -16,10 +12,10 @@ typedef struct { int64_t version; - void *(*newWaiter)(void); - void (*awaitWaiter)(void *); - void *(*currentIsolate)(void); - void (*enterIsolate)(void *); + void* (*newWaiter)(void); + void (*awaitWaiter)(void*); + void* (*currentIsolate)(void); + void (*enterIsolate)(void*); void (*exitIsolate)(void); int64_t (*getMainPortId)(void); bool (*getCurrentThreadOwnsIsolate)(int64_t); @@ -27,115 +23,99 @@ id objc_retainBlock(id); -#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ - assert(ctx->version >= 1); \ - void *targetIsolate = ctx->currentIsolate(); \ - int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ - return BLOCK_SIG { \ - void *currentIsolate = ctx->currentIsolate(); \ - bool mayEnterIsolate = currentIsolate == NULL && ctx->getCurrentThreadOwnsIsolate != NULL && \ - ctx->getCurrentThreadOwnsIsolate(targetPort); \ - if (currentIsolate == targetIsolate || mayEnterIsolate) { \ - if (mayEnterIsolate) { \ - ctx->enterIsolate(targetIsolate); \ - } \ - INVOKE_DIRECT; \ - if (mayEnterIsolate) { \ - ctx->exitIsolate(); \ - } \ - } else { \ - void *waiter = ctx->newWaiter(); \ - INVOKE_LISTENER; \ - ctx->awaitWaiter(waiter); \ - } \ +#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ + assert(ctx->version >= 1); \ + void* targetIsolate = ctx->currentIsolate(); \ + int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ + return BLOCK_SIG { \ + void* currentIsolate = ctx->currentIsolate(); \ + bool mayEnterIsolate = \ + currentIsolate == NULL && \ + ctx->getCurrentThreadOwnsIsolate != NULL && \ + ctx->getCurrentThreadOwnsIsolate(targetPort); \ + if (currentIsolate == targetIsolate || mayEnterIsolate) { \ + if (mayEnterIsolate) { \ + ctx->enterIsolate(targetIsolate); \ + } \ + INVOKE_DIRECT; \ + if (mayEnterIsolate) { \ + ctx->exitIsolate(); \ + } \ + } else { \ + void* waiter = ctx->newWaiter(); \ + INVOKE_LISTENER; \ + ctx->awaitWaiter(waiter); \ + } \ }; -typedef void (^_ListenerTrampoline)(id arg0, id arg1); -__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline -_NativeLibrary_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { + +typedef void (^_ListenerTrampoline)(id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline _NativeLibrary_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1) { objc_retainBlock(block); - block((__bridge id)(__bridge_retained void *)(arg0), - (__bridge id)(__bridge_retained void *)(arg1)); + block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); }; } -typedef void (^_BlockingTrampoline)(void *waiter, id arg0, id arg1); -__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline -_NativeLibrary_wrapBlockingBlock_pfv6jd(_BlockingTrampoline block, - _BlockingTrampoline listenerBlock, - DOBJC_Context *ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL( - ctx, ^void(id arg0, id arg1), - { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void *)(arg0), - (__bridge id)(__bridge_retained void *)(arg1)); - }, - { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void *)(arg0), - (__bridge id)(__bridge_retained void *)(arg1)); - }); +typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline _NativeLibrary_wrapBlockingBlock_pfv6jd( + _BlockingTrampoline block, _BlockingTrampoline listenerBlock, + DOBJC_Context* ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1), { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + }, { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + }); } -typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); -__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_1 -_NativeLibrary_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_1 _NativeLibrary_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { return ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { objc_retainBlock(block); - block((__bridge id)(__bridge_retained void *)(arg0), - (__bridge id)(__bridge_retained void *)(arg1), arg2, - (__bridge id)(__bridge_retained void *)(arg3)); + block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); }; } -typedef void (^_BlockingTrampoline_1)(void *waiter, id arg0, id arg1, - CGImagePropertyOrientation arg2, id arg3); -__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_1 -_NativeLibrary_wrapBlockingBlock_10c3wkj(_BlockingTrampoline_1 block, - _BlockingTrampoline_1 listenerBlock, - DOBJC_Context *ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL( - ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), - { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void *)(arg0), - (__bridge id)(__bridge_retained void *)(arg1), arg2, - (__bridge id)(__bridge_retained void *)(arg3)); - }, - { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void *)(arg0), - (__bridge id)(__bridge_retained void *)(arg1), arg2, - (__bridge id)(__bridge_retained void *)(arg3)); - }); +typedef void (^_BlockingTrampoline_1)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_1 _NativeLibrary_wrapBlockingBlock_10c3wkj( + _BlockingTrampoline_1 block, _BlockingTrampoline_1 listenerBlock, + DOBJC_Context* ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + }, { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + }); } -typedef void (^_ListenerTrampoline_2)(id arg0); -__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_2 -_NativeLibrary_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline_2)(id arg0); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_2 _NativeLibrary_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { return ^void(id arg0) { objc_retainBlock(block); - block((__bridge id)(__bridge_retained void *)(arg0)); + block((__bridge id)(__bridge_retained void*)(arg0)); }; } -typedef void (^_BlockingTrampoline_2)(void *waiter, id arg0); -__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_2 -_NativeLibrary_wrapBlockingBlock_xtuoz7(_BlockingTrampoline_2 block, - _BlockingTrampoline_2 listenerBlock, - DOBJC_Context *ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL( - ctx, ^void(id arg0), - { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void *)(arg0)); - }, - { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void *)(arg0)); - }); +typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0); +__attribute__((visibility("default"))) __attribute__((used)) +_ListenerTrampoline_2 _NativeLibrary_wrapBlockingBlock_xtuoz7( + _BlockingTrampoline_2 block, _BlockingTrampoline_2 listenerBlock, + DOBJC_Context* ctx) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0), { + objc_retainBlock(block); + block(nil, (__bridge id)(__bridge_retained void*)(arg0)); + }, { + objc_retainBlock(listenerBlock); + listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0)); + }); } #undef BLOCKING_BLOCK_IMPL diff --git a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj index ca64b45abafe..e4d94762d52a 100644 --- a/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/macos/Runner.xcodeproj/project.pbxproj @@ -485,7 +485,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -567,7 +567,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -617,7 +617,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.15; + MACOSX_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index fcf7b2e48660..4a335c4eba54 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -40,7 +40,7 @@ dependencies: path: ^1.9.1 dev_dependencies: - ffigen: ^20.1.1 + ffigen: ^21.0.0 flutter_test: sdk: flutter From 41f3a984d8ab3b20a96f6bcce5c60d48fc2f7e43 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:41:23 -0400 Subject: [PATCH 348/398] change android openRead to not use length and add argument errors --- .../cross_file/lib/src/cross_file.dart | 11 +++++- .../android_scoped_storage_cross_file.dart | 38 +++++++++++-------- .../pigeons/android_library.dart | 8 ++-- ...ndroid_scoped_storage_cross_file_test.dart | 3 -- .../src/darwin_scoped_storage_cross_file.dart | 9 ++++- 5 files changed, 45 insertions(+), 24 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index ec3cfb0230f9..ee78ec6a96da 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -93,7 +93,16 @@ base class XFile extends XEntity { /// /// Platforms may throw an exception if there is an error opening or reading /// the resource. - Stream openRead([int? start, int? end]) => platform.openRead(start, end); + Stream openRead([int? start, int? end]) { + if (start != null && start < 0) { + throw ArgumentError('`start` must be greater than 0. start: $start'); + } else if (end != null && end <= (start ?? 0)) { + throw ArgumentError( + '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', + ); + } + return platform.openRead(start, end); + } /// Reads the entire resource contents as a list of bytes. /// diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 8fa55688f731..daf4dfd390b1 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'dart:convert'; -import 'dart:math'; import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -51,27 +50,36 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { @override Stream openRead([int? start, int? end]) async* { - final int? fileLength = await length(); - if (fileLength == null) { - throw UnsupportedError('Cannot access file length.'); + if (start != null && start < 0) { + throw ArgumentError('`start` must be greater than 0. start: $start'); + } else if (end != null && end <= (start ?? 0)) { + throw ArgumentError( + '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', + ); } - int bytesToRead = (end ?? fileLength) - (start ?? 0); - assert(bytesToRead >= 0); - final android.InputStream? inputStream = await _contentResolver.openInputStream(params.uri); - if (inputStream case final android.InputStream inputStream) { - if (start != null && start > 0) { - await inputStream.skip(start); + int currentByteIndex = start ?? 0; + + if (currentByteIndex > 0) { + await inputStream.skip(currentByteIndex); } - late Uint8List bytes; + late Uint8List chunk; do { - bytes = await inputStream.readBytes(min(bytesToRead, maxByteArrayLen)); - yield bytes; - bytesToRead -= bytes.length; - } while (bytesToRead > 0 && bytes.isNotEmpty); + chunk = await inputStream.readBytes(maxByteArrayLen); + + if (chunk.isNotEmpty) { + if (end == null) { + yield chunk; + } else { + yield Uint8List.sublistView(chunk, 0, end - currentByteIndex); + } + } + + currentByteIndex += chunk.length; + } while (chunk.isNotEmpty && (end == null || currentByteIndex < end)); } else { throw NullInputStreamError(params.uri); } diff --git a/packages/cross_file/cross_file_android/pigeons/android_library.dart b/packages/cross_file/cross_file_android/pigeons/android_library.dart index a95b24eb5ee3..a38858a066db 100644 --- a/packages/cross_file/cross_file_android/pigeons/android_library.dart +++ b/packages/cross_file/cross_file_android/pigeons/android_library.dart @@ -85,9 +85,11 @@ abstract class ContentResolver { /// See https://developer.android.com/reference/java/io/InputStream. @ProxyApi(kotlinOptions: KotlinProxyApiOptions(fullClassName: 'java.io.InputStream')) abstract class InputStream { - /// Reads some number of bytes from the input stream and stores them into the - /// returns them. - Uint8List readBytes(int len); + /// Read up to a `maxLength` of bytes from the input stream. + /// + /// Returns a `Uint8List` with a length of the bytes read even if it less than + /// `maxLength`. + Uint8List readBytes(int maxLength); /// Reads all remaining bytes from the input stream. Uint8List readAllBytes(); diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart index 9db438f03b14..9a918e9ec009 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_file_test.dart @@ -63,7 +63,6 @@ void main() { final testBytes = Uint8List.fromList([0, 1, 2]); final mockDocumentFile = MockDocumentFile(); - when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { @@ -91,7 +90,6 @@ void main() { ); final mockDocumentFile = MockDocumentFile(); - when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { @@ -117,7 +115,6 @@ void main() { final testBytes = Uint8List.fromList([0, 0, 0, 1, 1, 1, 0, 0, 0]); final mockDocumentFile = MockDocumentFile(); - when(mockDocumentFile.length()).thenAnswer((_) async => testBytes.length); const uri = 'uri'; android.PigeonOverrides.documentFile_fromSingleUri = ({required String singleUri}) { diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 68fe3d4c813a..ddaea3119450 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -199,8 +199,13 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile @override Stream openRead([int? start, int? end]) { - assert(start == null || start >= 0); - assert(end == null || end >= (start ?? 0)); + if (start != null && start < 0) { + throw ArgumentError('`start` must be greater than 0. start: $start'); + } else if (end != null && end <= (start ?? 0)) { + throw ArgumentError( + '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', + ); + } final streamController = StreamController(); From 7e4cf132a7e14f3d25b3fdc31d040db1c9b9e60b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:48:44 -0400 Subject: [PATCH 349/398] change to exception for input stream --- .../android_scoped_storage_cross_file.dart | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index daf4dfd390b1..a15eb570d709 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -81,7 +81,7 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { currentByteIndex += chunk.length; } while (chunk.isNotEmpty && (end == null || currentByteIndex < end)); } else { - throw NullInputStreamError(params.uri); + throw NullInputStreamException(params.uri); } } @@ -92,7 +92,7 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { return inputStream.readAllBytes(); } - throw NullInputStreamError(params.uri); + throw NullInputStreamException(params.uri); } @override @@ -113,11 +113,16 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { } /// Error thrown when the native [android.InputStream] is not accessible. -class NullInputStreamError extends UnsupportedError { - /// Constructs a [NullInputStreamError]. - NullInputStreamError(String uri) - : super( - 'Failed to get native InputStream from file with path: $uri. ' - 'App may not have permissions to access file.', - ); +final class NullInputStreamException implements Exception { + /// Constructs a [NullInputStreamException]. + NullInputStreamException(this.uri); + + /// The URI the input stream that was request for. + final String uri; + + @override + String toString() { + return 'NullInputStreamException: Failed to get native InputStream from file with path: $uri. ' + 'App may not have permissions to access file.'; + } } From 2cd672f83c8f8b50cd4ba1c103651574e998727e Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:58:15 -0400 Subject: [PATCH 350/398] simplify darwing --- .../lib/src/byte_range_filter.dart | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart b/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart index 95dc7082eb5b..22308fbc6492 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/byte_range_filter.dart @@ -7,7 +7,7 @@ import 'dart:typed_data'; /// Byte range filter for a continuous stream of data. /// -/// Takes incoming chunks of bytes (Uint8List) as they arrive, and slices out +/// Takes incoming chunks of bytes ([Uint8List]) as they arrive, and slices out /// only the portion that falls within a specific ([start], [end]) index range. /// /// All byte chunks are passed to [addBytes] which returns only the bytes that @@ -31,33 +31,28 @@ class ByteRangeFilter { /// Returns a list of bytes if they are within the desired range of [start] /// and [end]. Otherwise, returns an empty list. Uint8List addBytes(Uint8List bytes) { - Uint8List? inRangeBytes; - final int newByteIndex = _currentByteIndex + bytes.length; - - if (end == null) { - if (_currentByteIndex >= start) { - inRangeBytes = bytes; - } else { - if (newByteIndex > start) { - inRangeBytes = bytes.sublist(start - _currentByteIndex); - } - } - } else if (end case final int end) { - final int bytesLeftToRead = end - max(_currentByteIndex, start); - - if (bytesLeftToRead > 0) { - if (_currentByteIndex >= start) { - inRangeBytes = bytes.sublist(0, min(bytesLeftToRead, bytes.length)); - } else if (newByteIndex > start) { - inRangeBytes = bytes.sublist( - start - _currentByteIndex, - min(start - _currentByteIndex + bytesLeftToRead, bytes.length), - ); - } - } + final int chunkStart = _currentByteIndex; + final int chunkEnd = chunkStart + bytes.length; + _currentByteIndex = chunkEnd; + + // 1. Early-exit short-circuit + if (end != null && chunkStart >= end!) { + return Uint8List(0); + } + + // 2. Compute absolute interval intersection + final int intersectStart = max(chunkStart, start); + final int intersectEnd = end == null ? chunkEnd : min(chunkEnd, end!); + + if (intersectStart < intersectEnd) { + // 3. Convert absolute indices to chunk-local offsets + final int localStart = intersectStart - chunkStart; + final int localEnd = intersectEnd - chunkStart; + + // 4. Zero-copy view + return Uint8List.sublistView(bytes, localStart, localEnd); } - _currentByteIndex = newByteIndex; - return inRangeBytes ?? Uint8List(0); + return Uint8List(0); } } From 1ebabfc299e4e683fc3f91190bd9a8f57a695b41 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sun, 2 Aug 2026 09:45:01 -0400 Subject: [PATCH 351/398] use reader for open read --- .../cross_file_web/lib/src/web_helpers.dart | 14 ++++++++++++++ .../lib/src/web_scoped_storage_cross_file.dart | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index f9af59765ced..89116e52f53a 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -89,6 +89,20 @@ Future fetchBlob(String objectUrl) async { } } +/// Converts a [ReadableStream] to a [Stream] of [Uint8List]. +Stream readableStreamToStream(ReadableStream stream) async* { + final reader = stream.getReader() as ReadableStreamDefaultReader; + try { + late ReadableStreamReadResult chunk; + do { + chunk = await reader.read().toDart; + yield (chunk.value! as JSUint8Array).toDart; + } while(!chunk.done); + } finally { + reader.releaseLock(); + } +} + /// Overrides some functions to allow testing. // TODO(dit): https://github.com/flutter/flutter/issues/91400 // Move this to web_helpers_test.dart diff --git a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart index c7c5e60e959e..6556ffeeaf80 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart @@ -139,7 +139,7 @@ base class WebScopedStorageXFile extends PlatformScopedStorageXFile Stream openRead([int? start, int? end]) async* { final Blob blob = await getBlob(); final Blob slice = blob.slice(start ?? 0, end ?? blob.size, blob.type); - yield await blobToBytes(slice); + yield* readableStreamToStream(slice.stream()); } @override From 5c95bc6ef8c9dffacd846968cd5b61c75e774dcb Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sun, 2 Aug 2026 14:48:44 -0400 Subject: [PATCH 352/398] passing web integration tests --- .../cross_file/cross_file_web/lib/src/web_helpers.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart index 89116e52f53a..c4666b026b14 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_helpers.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_helpers.dart @@ -91,13 +91,15 @@ Future fetchBlob(String objectUrl) async { /// Converts a [ReadableStream] to a [Stream] of [Uint8List]. Stream readableStreamToStream(ReadableStream stream) async* { + // Always returns `ReadableStreamDefaultReader` if no options are passed to + // `getReader`. final reader = stream.getReader() as ReadableStreamDefaultReader; try { - late ReadableStreamReadResult chunk; - do { - chunk = await reader.read().toDart; + ReadableStreamReadResult chunk = await reader.read().toDart; + while (!chunk.done) { yield (chunk.value! as JSUint8Array).toDart; - } while(!chunk.done); + chunk = await reader.read().toDart; + } } finally { reader.releaseLock(); } From 40dd018f5166c5ab8fc3d656da132f12f0943b83 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sun, 2 Aug 2026 15:02:20 -0400 Subject: [PATCH 353/398] move tests instructions to contributing --- packages/cross_file/cross_file_web/CONTRIBUTING.md | 6 ++++++ packages/cross_file/cross_file_web/README.md | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 packages/cross_file/cross_file_web/CONTRIBUTING.md diff --git a/packages/cross_file/cross_file_web/CONTRIBUTING.md b/packages/cross_file/cross_file_web/CONTRIBUTING.md new file mode 100644 index 000000000000..ed2376e12558 --- /dev/null +++ b/packages/cross_file/cross_file_web/CONTRIBUTING.md @@ -0,0 +1,6 @@ +# Contributing to `cross_file_web` + +### Tests + +This package only contains integration tests found in `example/integration_test`. Instructions to +run integration tests can be found in the [example README.](./example/README.md) diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md index 7348da8be6da..302ff72262bd 100644 --- a/packages/cross_file/cross_file_web/README.md +++ b/packages/cross_file/cross_file_web/README.md @@ -28,9 +28,5 @@ its size is known beforehand), so that case can be handled programmatically. [![Data on Global support for Blob URLs](https://caniuse.bitsofco.de/image/bloburls.png)](https://caniuse.com/bloburls) -### Tests - -Tests for the web platform can be run with `flutter test --platform chrome`. - [1]: https://pub.dev/packages/cross_file [2]: https://flutter.dev/to/endorsed-federated-plugin From 17aa449bb1a83d4adec6e49a18dad55b8ad46321 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Sun, 2 Aug 2026 15:16:56 -0400 Subject: [PATCH 354/398] cleanup android code a bit --- .../android_scoped_storage_cross_file.dart | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index a15eb570d709..7f64941c6480 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -66,20 +66,17 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { await inputStream.skip(currentByteIndex); } - late Uint8List chunk; - do { - chunk = await inputStream.readBytes(maxByteArrayLen); - - if (chunk.isNotEmpty) { - if (end == null) { - yield chunk; - } else { - yield Uint8List.sublistView(chunk, 0, end - currentByteIndex); - } + Uint8List chunk = await inputStream.readBytes(maxByteArrayLen); + while (chunk.isNotEmpty && (end == null || currentByteIndex < end)) { + if (end == null) { + yield chunk; + } else { + yield Uint8List.sublistView(chunk, 0, end - currentByteIndex); } - currentByteIndex += chunk.length; - } while (chunk.isNotEmpty && (end == null || currentByteIndex < end)); + + chunk = await inputStream.readBytes(maxByteArrayLen); + } } else { throw NullInputStreamException(params.uri); } From a9326a7454e14ecebd1909aea66e5a0bb7b0e273 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 10:53:33 -0400 Subject: [PATCH 355/398] typo --- packages/cross_file/cross_file/lib/src/cross_file.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index ee78ec6a96da..d4068b963251 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -121,6 +121,6 @@ base class XFile extends XEntity { /// doesn't exist or information is not available. /// /// If the file is identified by a path, only the base name of the file will - /// gbe included in the name. + /// be included in the name. Future name() => platform.name(); } From 6a12a0f8afa97fa7b4dbbb77d63f4f0c39e740ee Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 11:50:52 -0400 Subject: [PATCH 356/398] remove file selector references --- .../cross_file/example/lib/main.dart | 27 +++++---- .../cross_file/example/pubspec.yaml | 43 ++++----------- packages/cross_file/cross_file/pubspec.yaml | 31 ++++------- .../cross_file_android/example/lib/main.dart | 43 +++++++++------ .../cross_file_android/example/pubspec.yaml | 28 ++++------ .../cross_file_android/pubspec.yaml | 13 ++--- .../cross_file_darwin/example/lib/main.dart | 53 +++++++++--------- .../cross_file_darwin/example/pubspec.yaml | 21 ++----- .../cross_file/cross_file_darwin/pubspec.yaml | 13 ++--- .../cross_file_io/example/lib/main.dart | 40 +++++++++----- .../cross_file_io/example/pubspec.yaml | 30 +++------- .../cross_file_io/lib/cross_file_io.dart | 4 +- .../cross_file/cross_file_io/pubspec.yaml | 7 +-- .../cross_file_web/example/lib/main.dart | 55 +++++-------------- .../cross_file_web/example/pubspec.yaml | 38 ++++--------- .../cross_file/cross_file_web/pubspec.yaml | 7 +-- 16 files changed, 179 insertions(+), 274 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/main.dart b/packages/cross_file/cross_file/example/lib/main.dart index 2107c6cbe6f8..f8bb3dda8d8c 100644 --- a/packages/cross_file/cross_file/example/lib/main.dart +++ b/packages/cross_file/cross_file/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:file_selector/file_selector.dart'; +import 'package:cross_file/cross_file.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -15,8 +15,18 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); + Future _getTextFile() async { + // Implement this method to retrieve a text file. + return null; + } + + Future _getDirectory() async { + // Implement this method to retrieve a directory. + return null; + } + + Future _openTextFile(BuildContext context) async { + final XFile? file = await _getTextFile(); if (file != null) { final String filename = await file.name() ?? file.uri; @@ -34,9 +44,6 @@ class FileOpenScreen extends StatelessWidget { case _: debugPrint('File Uri: ${file.uri}'); debugPrint('Filename: $filename'); - if (file is ScopedStorageXFile) { - debugPrint('Can Read File: ${await file.canRead()}'); - } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; @@ -47,7 +54,7 @@ class FileOpenScreen extends StatelessWidget { } Future _openDirectory() async { - final XDirectory? directory = await getDirectoryPath(); + final XDirectory? directory = await _getDirectory(); if (directory != null) { debugPrint('Directory Uri: ${directory.uri}'); @@ -71,7 +78,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), + appBar: AppBar(title: const Text('Open a Text File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -81,8 +88,8 @@ class FileOpenScreen extends StatelessWidget { foregroundColor: Colors.blue, backgroundColor: Colors.white, ), - child: const Text('Open File'), - onPressed: () => _openFile(context), + child: const Text('Open Text File'), + onPressed: () => _openTextFile(context), ), ElevatedButton( style: ElevatedButton.styleFrom( diff --git a/packages/cross_file/cross_file/example/pubspec.yaml b/packages/cross_file/cross_file/example/pubspec.yaml index affcd86334e1..ebb8a7742c14 100644 --- a/packages/cross_file/cross_file/example/pubspec.yaml +++ b/packages/cross_file/cross_file/example/pubspec.yaml @@ -13,30 +13,19 @@ dependencies: # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file + path: ../ + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_android` is released. + cross_file_android: + path: ../../cross_file_android + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_darwin` is released. cross_file_darwin: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_darwin + path: ../../cross_file_darwin + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_io` is released. cross_file_io: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_io + path: ../../cross_file_io + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_web` is released. cross_file_web: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_web - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector + path: ../../cross_file_web flutter: sdk: flutter mime: ^2.0.0 @@ -54,15 +43,3 @@ flutter: uses-material-design: true assets: - assets/hello.txt - -dependency_overrides: - # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because - # the updated file_selector branch depends on cross_file from git and this overrides its - # dependency. - cross_file: - # When depending on this package from a real application you should use: - # cross_file: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ \ No newline at end of file diff --git a/packages/cross_file/cross_file/pubspec.yaml b/packages/cross_file/cross_file/pubspec.yaml index b4cd825ef03a..f9f702c34f44 100644 --- a/packages/cross_file/cross_file/pubspec.yaml +++ b/packages/cross_file/cross_file/pubspec.yaml @@ -26,31 +26,22 @@ flutter: default_package: cross_file_io dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_android` is released. cross_file_android: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_android + path: ../cross_file_android + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_darwin` is released. cross_file_darwin: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_darwin + path: ../cross_file_darwin + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_io` is released. cross_file_io: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_io + path: ../cross_file_io + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface + path: ../cross_file_platform_interface + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_web` is released. cross_file_web: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_web + path: ../cross_file_web flutter: sdk: flutter diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 2107c6cbe6f8..665fd111009e 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:file_selector/file_selector.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -15,11 +15,21 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); + Future _getTextFile() async { + // Implement this method to retrieve a text file. + return null; + } + + Future _getDirectory() async { + // Implement this method to retrieve a directory. + return null; + } + + Future _openTextFile(BuildContext context) async { + final PlatformXFile? file = await _getTextFile(); if (file != null) { - final String filename = await file.name() ?? file.uri; + final String filename = await file.name() ?? file.params.uri; switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): @@ -32,11 +42,8 @@ class FileOpenScreen extends StatelessWidget { ); } case _: - debugPrint('File Uri: ${file.uri}'); + debugPrint('File Uri: ${file.params.uri}'); debugPrint('Filename: $filename'); - if (file is ScopedStorageXFile) { - debugPrint('Can Read File: ${await file.canRead()}'); - } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; @@ -47,20 +54,20 @@ class FileOpenScreen extends StatelessWidget { } Future _openDirectory() async { - final XDirectory? directory = await getDirectoryPath(); + final PlatformXDirectory? directory = await _getDirectory(); if (directory != null) { - debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory Uri: ${directory.params.uri}'); debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XEntity entity in directory.list()) { + await for (final PlatformXEntity entity in directory.list(ListParams())) { switch (entity) { - case final XFile file: - final String filename = await file.name() ?? file.uri; + case final PlatformXFile file: + final String filename = await file.name() ?? file.params.uri; debugPrint('\tFile: $filename'); - case final XDirectory directory: - debugPrint('\tDirectory: ${directory.uri}'); + case final PlatformXDirectory directory: + debugPrint('\tDirectory: ${directory.params.uri}'); } } } else { @@ -71,7 +78,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), + appBar: AppBar(title: const Text('Open a Text File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -81,8 +88,8 @@ class FileOpenScreen extends StatelessWidget { foregroundColor: Colors.blue, backgroundColor: Colors.white, ), - child: const Text('Open File'), - onPressed: () => _openFile(context), + child: const Text('Open Text File'), + onPressed: () => _openTextFile(context), ), ElevatedButton( style: ElevatedButton.styleFrom( diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index f565d6ccf85f..ee446f16a758 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -7,11 +7,17 @@ environment: flutter: ">=3.38.0" dependencies: - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector + cross_file_android: + # When depending on this package from a real application you should use: + # cross_file_android: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. + cross_file_platform_interface: + path: ../../cross_file_platform_interface flutter: sdk: flutter mime: ^2.0.0 @@ -25,15 +31,3 @@ dev_dependencies: flutter: uses-material-design: true - -dependency_overrides: - # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because - # the updated file_selector branch depends on cross_file_android from git and this overrides its - # dependency. - cross_file_android: - # When depending on this package from a real application you should use: - # cross_file_android: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ diff --git a/packages/cross_file/cross_file_android/pubspec.yaml b/packages/cross_file/cross_file_android/pubspec.yaml index 019bc6ddecfd..05e81318a959 100644 --- a/packages/cross_file/cross_file_android/pubspec.yaml +++ b/packages/cross_file/cross_file_android/pubspec.yaml @@ -19,16 +19,13 @@ flutter: pluginClass: CrossFileAndroidPlugin dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_io` is released. cross_file_io: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_io + path: ../cross_file_io + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface + path: ../cross_file_platform_interface flutter: sdk: flutter diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index e4b89c24d838..665fd111009e 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:cross_file_darwin/cross_file_darwin.dart'; -import 'package:file_selector/file_selector.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -16,11 +15,21 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); + Future _getTextFile() async { + // Implement this method to retrieve a text file. + return null; + } + + Future _getDirectory() async { + // Implement this method to retrieve a directory. + return null; + } - if (file case final XFile file) { - final String filename = await file.name() ?? file.uri; + Future _openTextFile(BuildContext context) async { + final PlatformXFile? file = await _getTextFile(); + + if (file != null) { + final String filename = await file.name() ?? file.params.uri; switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): @@ -30,18 +39,11 @@ class FileOpenScreen extends StatelessWidget { context: context, builder: (BuildContext context) => TextDisplay(filename: filename, fileContents: fileContents), - ).then((_) { - file - .getExtension() - .stopAccessingSecurityScopedResource(); - }); + ); } case _: - debugPrint('File Uri: ${file.uri}'); + debugPrint('File Uri: ${file.params.uri}'); debugPrint('Filename: $filename'); - if (file is ScopedStorageXFile) { - debugPrint('Can Read File: ${await file.canRead()}'); - } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; @@ -52,21 +54,20 @@ class FileOpenScreen extends StatelessWidget { } Future _openDirectory() async { - final XDirectory? directory = await getDirectoryPath(); + final PlatformXDirectory? directory = await _getDirectory(); if (directory != null) { - debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory Uri: ${directory.params.uri}'); debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XEntity entity in directory.list()) { + await for (final PlatformXEntity entity in directory.list(ListParams())) { switch (entity) { - case final XFile file: - final String filename = await file.name() ?? file.uri; + case final PlatformXFile file: + final String filename = await file.name() ?? file.params.uri; debugPrint('\tFile: $filename'); - debugPrint('\t\tFile Length: ${await file.length()}'); - case final XDirectory directory: - debugPrint('\tDirectory: ${directory.uri}'); + case final PlatformXDirectory directory: + debugPrint('\tDirectory: ${directory.params.uri}'); } } } else { @@ -77,7 +78,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), + appBar: AppBar(title: const Text('Open a Text File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -87,8 +88,8 @@ class FileOpenScreen extends StatelessWidget { foregroundColor: Colors.blue, backgroundColor: Colors.white, ), - child: const Text('Open File'), - onPressed: () => _openFile(context), + child: const Text('Open Text File'), + onPressed: () => _openTextFile(context), ), ElevatedButton( style: ElevatedButton.styleFrom( diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 6ef0db20ba87..592134920cca 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -14,12 +14,11 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. + cross_file_platform_interface: + path: ../../cross_file_platform_interface cupertino_icons: ^1.0.8 - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector flutter: sdk: flutter mime: ^2.0.0 @@ -34,15 +33,3 @@ flutter: uses-material-design: true assets: - assets/hello.txt - -dependency_overrides: - # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because - # the updated file_selector branch depends on cross_file_darwin from git and this overrides its - # dependency. - cross_file_darwin: - # When depending on this package from a real application you should use: - # cross_file_darwin: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ \ No newline at end of file diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index 4a335c4eba54..ece106740b5e 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -23,16 +23,13 @@ flutter: sharedDarwinSource: true dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_io` is released. cross_file_io: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_io + path: ../cross_file_io + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface + path: ../cross_file_platform_interface ffi: ^2.2.0 flutter: sdk: flutter diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart index 3d04b30c42d7..665fd111009e 100644 --- a/packages/cross_file/cross_file_io/example/lib/main.dart +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:file_selector/file_selector.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -15,11 +15,21 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); + Future _getTextFile() async { + // Implement this method to retrieve a text file. + return null; + } + + Future _getDirectory() async { + // Implement this method to retrieve a directory. + return null; + } + + Future _openTextFile(BuildContext context) async { + final PlatformXFile? file = await _getTextFile(); if (file != null) { - final String filename = await file.name() ?? file.uri; + final String filename = await file.name() ?? file.params.uri; switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): @@ -32,7 +42,7 @@ class FileOpenScreen extends StatelessWidget { ); } case _: - debugPrint('File Uri: ${file.uri}'); + debugPrint('File Uri: ${file.params.uri}'); debugPrint('Filename: $filename'); debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); @@ -44,20 +54,20 @@ class FileOpenScreen extends StatelessWidget { } Future _openDirectory() async { - final XDirectory? directory = await getDirectoryPath(); + final PlatformXDirectory? directory = await _getDirectory(); if (directory != null) { - debugPrint('Directory Uri: ${directory.uri}'); + debugPrint('Directory Uri: ${directory.params.uri}'); debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final XEntity entity in directory.list()) { + await for (final PlatformXEntity entity in directory.list(ListParams())) { switch (entity) { - case final XFile file: - final String filename = await file.name() ?? file.uri; + case final PlatformXFile file: + final String filename = await file.name() ?? file.params.uri; debugPrint('\tFile: $filename'); - case final XDirectory directory: - debugPrint('\tDirectory: ${directory.uri}'); + case final PlatformXDirectory directory: + debugPrint('\tDirectory: ${directory.params.uri}'); } } } else { @@ -68,7 +78,7 @@ class FileOpenScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), + appBar: AppBar(title: const Text('Open a Text File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -78,8 +88,8 @@ class FileOpenScreen extends StatelessWidget { foregroundColor: Colors.blue, backgroundColor: Colors.white, ), - child: const Text('Open File'), - onPressed: () => _openFile(context), + child: const Text('Open Text File'), + onPressed: () => _openTextFile(context), ), ElevatedButton( style: ElevatedButton.styleFrom( diff --git a/packages/cross_file/cross_file_io/example/pubspec.yaml b/packages/cross_file/cross_file_io/example/pubspec.yaml index c5a2615988c7..e74ab789dd41 100644 --- a/packages/cross_file/cross_file_io/example/pubspec.yaml +++ b/packages/cross_file/cross_file_io/example/pubspec.yaml @@ -7,21 +7,17 @@ environment: flutter: ">=3.38.0" dependencies: - cross_file: + cross_file_io: # When depending on this package from a real application you should use: - # cross_file: ^x.y.z + # cross_file_io: ^x.y.z # See https://dart.dev/tools/pub/dependencies#version-constraints # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector + path: ../ + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. + cross_file_platform_interface: + path: ../../cross_file_platform_interface flutter: sdk: flutter mime: ^2.0.0 @@ -36,15 +32,3 @@ flutter: uses-material-design: true assets: - assets/hello.txt - -dependency_overrides: - # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because - # the updated file_selector branch depends on cross_file_io from git and this overrides its - # dependency. - cross_file_io: - # When depending on this package from a real application you should use: - # cross_file_io: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ \ No newline at end of file diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 3ca189ee7e24..62e105c08252 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -6,5 +6,5 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXDirectoryCreationParams, PlatformXEntity, PlatformXFileCreationParams; export 'src/cross_file_io.dart'; -export 'src/io_cross_directory.dart'; -export 'src/io_cross_file.dart'; +export 'src/io_cross_directory.dart' show IOXDirectoryExtension; +export 'src/io_cross_file.dart' show IOXFileExtension; diff --git a/packages/cross_file/cross_file_io/pubspec.yaml b/packages/cross_file/cross_file_io/pubspec.yaml index f4626e867b50..bc9a1780aed2 100644 --- a/packages/cross_file/cross_file_io/pubspec.yaml +++ b/packages/cross_file/cross_file_io/pubspec.yaml @@ -19,11 +19,10 @@ flutter: dartPluginClass: CrossFileIO dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface + path: ../cross_file_platform_interface flutter: sdk: flutter path: ^1.9.1 diff --git a/packages/cross_file/cross_file_web/example/lib/main.dart b/packages/cross_file/cross_file_web/example/lib/main.dart index 4fd5f49b8b5d..052bb98b341a 100644 --- a/packages/cross_file/cross_file_web/example/lib/main.dart +++ b/packages/cross_file/cross_file_web/example/lib/main.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:file_selector/file_selector.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/material.dart'; import 'package:mime/mime.dart' as mime; @@ -15,11 +15,16 @@ class FileOpenScreen extends StatelessWidget { /// Constructs a [FileOpenScreen]. const FileOpenScreen({super.key}); - Future _openFile(BuildContext context) async { - final XFile? file = await openFile(); + Future _getTextFile() async { + // Implement this method to retrieve a text file. + return null; + } + + Future _openTextFile(BuildContext context) async { + final PlatformXFile? file = await _getTextFile(); if (file != null) { - final String filename = await file.name() ?? file.uri; + final String filename = await file.name() ?? file.params.uri; switch (mime.lookupMimeType(filename)) { case final String mimeType when mimeType.startsWith('text'): @@ -32,11 +37,8 @@ class FileOpenScreen extends StatelessWidget { ); } case _: - debugPrint('File Uri: ${file.uri}'); + debugPrint('File Uri: ${file.params.uri}'); debugPrint('Filename: $filename'); - if (file is ScopedStorageXFile) { - debugPrint('Can Read File: ${await file.canRead()}'); - } debugPrint('File Length: ${await file.length()}'); debugPrint('File Last Modified: ${await file.lastModified()}'); return; @@ -46,33 +48,10 @@ class FileOpenScreen extends StatelessWidget { } } - Future _openDirectory() async { - final XDirectory? directory = await getDirectoryPath(); - - if (directory != null) { - debugPrint('Directory Uri: ${directory.uri}'); - debugPrint('Directory exists: ${await directory.exists()}'); - - debugPrint('List of Entities:'); - await for (final XEntity entity in directory.list()) { - switch (entity) { - case final XFile file: - final String filename = await file.name() ?? file.uri; - debugPrint('\tFile: $filename'); - debugPrint('\t\tFile Length: ${await file.length()}'); - case final XDirectory directory: - debugPrint('\tDirectory: ${directory.uri}'); - } - } - } else { - debugPrint('No directory selected.'); - } - } - @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Open a File'), backgroundColor: Colors.blue), + appBar: AppBar(title: const Text('Open a Text File'), backgroundColor: Colors.blue), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -82,16 +61,8 @@ class FileOpenScreen extends StatelessWidget { foregroundColor: Colors.blue, backgroundColor: Colors.white, ), - child: const Text('Open File'), - onPressed: () => _openFile(context), - ), - ElevatedButton( - style: ElevatedButton.styleFrom( - foregroundColor: Colors.blue, - backgroundColor: Colors.white, - ), - child: const Text('Open Directory'), - onPressed: () => _openDirectory(), + child: const Text('Open Text File'), + onPressed: () => _openTextFile(context), ), ], ), diff --git a/packages/cross_file/cross_file_web/example/pubspec.yaml b/packages/cross_file/cross_file_web/example/pubspec.yaml index ef662828263f..b44e0a75d32c 100644 --- a/packages/cross_file/cross_file_web/example/pubspec.yaml +++ b/packages/cross_file/cross_file_web/example/pubspec.yaml @@ -6,40 +6,24 @@ environment: flutter: ">=3.38.0" dependencies: - file_selector: - git: - url: https://github.com/bparrishMines/packages - ref: new_file_selector - path: packages/file_selector/file_selector + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. + cross_file_platform_interface: + path: ../../cross_file_platform_interface + cross_file_web: + # When depending on this package from a real application you should use: + # cross_file_web: ^x.y.z + # See https://dart.dev/tools/pub/dependencies#version-constraints + # The example app is bundled with the plugin so we use a path dependency on + # the parent directory to use the current plugin's version. + path: ../ flutter: sdk: flutter mime: ^2.0.0 dev_dependencies: - cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface - cross_file_web: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_web flutter_test: sdk: flutter integration_test: sdk: flutter web: ">=0.5.1 <2.0.0" - -dependency_overrides: - # TODO(bparrishMines): This should be moved to dependencies. This is currently placed here because - # the updated file_selector branch depends on cross_file_web from git and this overrides its - # dependency. - cross_file_web: - # When depending on this package from a real application you should use: - # cross_file_web: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ diff --git a/packages/cross_file/cross_file_web/pubspec.yaml b/packages/cross_file/cross_file_web/pubspec.yaml index eb64bf911e8e..6b7b91337a03 100644 --- a/packages/cross_file/cross_file_web/pubspec.yaml +++ b/packages/cross_file/cross_file_web/pubspec.yaml @@ -18,11 +18,10 @@ flutter: fileName: cross_file_web.dart dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_platform_interface` is + # released. cross_file_platform_interface: - git: - url: https://github.com/bparrishMines/packages - ref: new_crossfile - path: packages/cross_file/cross_file_platform_interface + path: ../cross_file_platform_interface flutter: sdk: flutter flutter_web_plugins: From 36822dfdc4f2b880dd1cfba9b819b83826ce37fb Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:05:54 -0400 Subject: [PATCH 357/398] move test to cross_file_io --- .../integration_test/cross_file_test.dart | 23 +++--------------- .../integration_test/cross_file_io_test.dart | 24 ++++++++++++++++--- .../cross_file_io/example/pubspec.yaml | 2 ++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart index 1093c380cd81..621977be68c7 100644 --- a/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart +++ b/packages/cross_file/cross_file/example/integration_test/cross_file_test.dart @@ -2,30 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:io'; - -import 'package:cross_file/cross_file.dart'; -import 'package:cross_file_io/cross_file_io.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; -import 'package:path/path.dart' as path; -import 'package:path_provider/path_provider.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - testWidgets('Can read from file using dart:io implementation', (WidgetTester tester) async { - final Directory dir = await getApplicationCacheDirectory(); - - final xDir = XDirectory.fromPath(dir.path); - expect(await xDir.exists(), isTrue); - - final file = XFile.fromPath(path.join(dir.path, 'hello.txt')); - file.getExtension()!.file - ..createSync() - ..writeAsStringSync('Hello, World!'); - - expect(await file.readAsString(), 'Hello, World!'); - }, skip: kIsWeb); + // Since this test is lacking integration tests, this test ensures the example + // app can be launched on an emulator/device. + testWidgets('Launch Test', (WidgetTester tester) async {}); } diff --git a/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart b/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart index 621977be68c7..8f654f271fd0 100644 --- a/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart +++ b/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart @@ -2,13 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - // Since this test is lacking integration tests, this test ensures the example - // app can be launched on an emulator/device. - testWidgets('Launch Test', (WidgetTester tester) async {}); + testWidgets('Can read from file using dart:io implementation', (WidgetTester tester) async { + final Directory dir = await getApplicationCacheDirectory(); + + final xDir = PlatformXDirectory(PlatformXDirectoryCreationParams(uri: dir.uri.toString())); + expect(await xDir.exists(), isTrue); + + final file = PlatformXFile( + PlatformXFileCreationParams(uri: path.join(dir.uri.toString(), 'hello.txt')), + ); + (file.extension! as IOXFileExtension).file + ..createSync() + ..writeAsStringSync('Hello, World!'); + + expect(await file.readAsString(), 'Hello, World!'); + }); } diff --git a/packages/cross_file/cross_file_io/example/pubspec.yaml b/packages/cross_file/cross_file_io/example/pubspec.yaml index e74ab789dd41..4dea15b165ca 100644 --- a/packages/cross_file/cross_file_io/example/pubspec.yaml +++ b/packages/cross_file/cross_file_io/example/pubspec.yaml @@ -27,6 +27,8 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + path: ^1.9.1 + path_provider: ^2.1.6 flutter: uses-material-design: true From f12a724ef6b1e209f95f71c2ff8bba530b5696fc Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:15:40 -0400 Subject: [PATCH 358/398] add a breaking change --- packages/cross_file/cross_file/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/cross_file/cross_file/CHANGELOG.md b/packages/cross_file/cross_file/CHANGELOG.md index ebf4322decb7..0942367a8404 100644 --- a/packages/cross_file/cross_file/CHANGELOG.md +++ b/packages/cross_file/cross_file/CHANGELOG.md @@ -1,6 +1,11 @@ ## 0.4.0 * Updates `cross_file` to a package-separated federated plugin. +* Adds `XDirectory` to access file containers. +* Adds file implementation for scoped storage APIs that use ephemeral URLS. See `ScopedStorageXFile` + and `ScopedStorageXDirector`. +* **Breaking Change** Removes `XFile.saveTo` because not all platform implementations support this + feature. gSee `README` for accessing platform-specific features. ## 0.3.5+4 From 7dc7720a3ba945768322342e165809863f53df8f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:33:06 -0400 Subject: [PATCH 359/398] change to checking with a top level class with functions --- .../example/lib/readme_excerpts.dart | 19 +++++++------- .../cross_file/cross_file/lib/cross_file.dart | 25 +++++++++++++++++++ .../lib/src/cross_file_android.dart | 4 --- .../lib/src/cross_file_darwin.dart | 4 --- .../cross_file_io/lib/src/cross_file_io.dart | 3 --- .../lib/src/cross_file_web.dart | 3 --- 6 files changed, 35 insertions(+), 23 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 42aa7bc5bb70..054a5d125f9b 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -34,15 +34,16 @@ Future accessPlatformFeatures() async { // #docregion platform_features late final XFile file; - if (CrossFileWeb.isCurrentImplementation()) { - final params = WebScopedStorageXFileCreationParams.fromObjectUrl( - objectUrl: 'blob:https://some/url:for/file', - ); - file = XFile.fromCreationParams(params); - } else if (CrossFileDarwin.isCurrentImplementation()) { - file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); - } else { - file = XFile.fromUri(Uri.file('/my/file.txt')); + switch (CrossFile.implementation) { + case CrossFileWeb(): + final params = WebScopedStorageXFileCreationParams.fromObjectUrl( + objectUrl: 'blob:https://some/url:for/file', + ); + file = XFile.fromCreationParams(params); + case CrossFileDarwin(): + file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); + default: + file = XFile.fromUri(Uri.file('/my/file.txt')); } await file diff --git a/packages/cross_file/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart index b728b35fa63d..571863764873 100644 --- a/packages/cross_file/cross_file/lib/cross_file.dart +++ b/packages/cross_file/cross_file/lib/cross_file.dart @@ -2,8 +2,33 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; + export 'src/cross_directory.dart'; export 'src/cross_entity.dart'; export 'src/cross_file.dart'; export 'src/scoped_storage_cross_directory.dart'; export 'src/scoped_storage_cross_file.dart'; + +/// Provides top level functions for the `cross_file` package. +final class CrossFile { + /// The current platform implementation. + /// + /// The platform implementation is set automatically at runtime based on the + /// target platform. Use this to check which platform is currently set. + /// + /// ```dart + /// switch (CrossFile.implementation) { + /// case CrossFileWeb(): + /// final params = WebScopedStorageXFileCreationParams.fromObjectUrl( + /// objectUrl: 'blob:https://some/url:for/file', + /// ); + /// file = XFile.fromCreationParams(params); + /// case CrossFileDarwin(): + /// file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); + /// default: + /// file = XFile.fromUri(Uri.file('/my/file.txt')); + /// } + /// ``` + static CrossFilePlatform? get implementation => CrossFilePlatform.instance; +} diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index e57ab7ade60d..b3b6c47a5017 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -15,10 +15,6 @@ base class CrossFileAndroid extends CrossFileIO { CrossFilePlatform.instance = CrossFileAndroid(); } - /// Whether the current implementation of `cross_file` is [CrossFileAndroid]. - static bool isCurrentImplementation() => - CrossFilePlatform.instance.runtimeType == CrossFileAndroid; - @override AndroidScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index a6d08b9211d5..2895499b9071 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -18,10 +18,6 @@ base class CrossFileDarwin extends CrossFileIO { ffi.DynamicLibrary.open('/System/Library/Frameworks/Photos.framework/Photos'); } - /// Whether the current implementation of `cross_file` is [CrossFileDarwin]. - static bool isCurrentImplementation() => - CrossFilePlatform.instance.runtimeType == CrossFileDarwin; - @override DarwinScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index 8d0126ca12d2..40753d920f91 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -14,9 +14,6 @@ base class CrossFileIO extends CrossFilePlatform { CrossFilePlatform.instance = CrossFileIO(); } - /// Whether the current implementation of `cross_file` is [CrossFileIO]. - static bool isCurrentImplementation() => CrossFilePlatform.instance.runtimeType == CrossFileIO; - @override IOXFile createPlatformXFile(PlatformXFileCreationParams params) { return IOXFile(params); diff --git a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart index 97b03b08e0ed..5559639b05c3 100644 --- a/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/src/cross_file_web.dart @@ -14,9 +14,6 @@ base class CrossFileWeb extends CrossFilePlatform { CrossFilePlatform.instance = CrossFileWeb(); } - /// Whether the current implementation of `cross_file` is [CrossFileWeb]. - static bool isCurrentImplementation() => CrossFilePlatform.instance.runtimeType == CrossFileWeb; - @override WebScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, From 50fc6f87792048b73e7fc1a882c3521bb75bfd4f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:40:33 -0400 Subject: [PATCH 360/398] update changelog --- packages/cross_file/cross_file/CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/CHANGELOG.md b/packages/cross_file/cross_file/CHANGELOG.md index 0942367a8404..816dd7422428 100644 --- a/packages/cross_file/cross_file/CHANGELOG.md +++ b/packages/cross_file/cross_file/CHANGELOG.md @@ -4,8 +4,11 @@ * Adds `XDirectory` to access file containers. * Adds file implementation for scoped storage APIs that use ephemeral URLS. See `ScopedStorageXFile` and `ScopedStorageXDirector`. -* **Breaking Change** Removes `XFile.saveTo` because not all platform implementations support this - feature. gSee `README` for accessing platform-specific features. +* **Breaking Change** Replaces `XFile(String path)` with `XFile.fromPath(String path)`. +* **Breaking Change** Removes `XFile.fromDatag`. +* **Breaking Change** Removes `XFile.saveTo`. +* **Breaking Change** Removes `mimeType` and `path`. +* **Breaking Change** Changes `XFile.name` to return `Future` rather than `String`. ## 0.3.5+4 From 9a41e2def527c9db03bc43e2854a723ec7bb3b95 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:46:52 -0400 Subject: [PATCH 361/398] update gradle --- .../cross_file/example/android/app/build.gradle.kts | 12 ++++++------ .../cross_file/example/android/gradle.properties | 7 ++++++- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- .../cross_file/example/android/settings.gradle.kts | 4 ++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle.kts b/packages/cross_file/cross_file/example/android/app/build.gradle.kts index b8f95097948d..1983fa252654 100644 --- a/packages/cross_file/cross_file/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file/example/android/app/build.gradle.kts @@ -1,6 +1,5 @@ plugins { id("com.android.application") - id("kotlin-android") id("dev.flutter.flutter-gradle-plugin") } @@ -14,10 +13,6 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = JavaVersion.VERSION_17.toString() - } - defaultConfig { applicationId = "dev.flutter.packages.cross_file_example" minSdk = flutter.minSdkVersion @@ -37,6 +32,12 @@ android { } } +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + flutter { source = "../.." } @@ -47,4 +48,3 @@ dependencies { androidTestImplementation("androidx.test.espresso:espresso-core:3.2.0") api("androidx.test:core:1.4.0") } - diff --git a/packages/cross_file/cross_file/example/android/gradle.properties b/packages/cross_file/cross_file/example/android/gradle.properties index fbee1d8cdafc..6146589810a7 100644 --- a/packages/cross_file/cross_file/example/android/gradle.properties +++ b/packages/cross_file/cross_file/example/android/gradle.properties @@ -1,2 +1,7 @@ -org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.jvmargs=-Xmx4G android.useAndroidX=true + +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties b/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties index e4ef43fb98df..a20f2c46d22e 100644 --- a/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/packages/cross_file/cross_file/example/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.1-all.zip diff --git a/packages/cross_file/cross_file/example/android/settings.gradle.kts b/packages/cross_file/cross_file/example/android/settings.gradle.kts index e3993757c096..68cc20cd41e9 100644 --- a/packages/cross_file/cross_file/example/android/settings.gradle.kts +++ b/packages/cross_file/cross_file/example/android/settings.gradle.kts @@ -20,8 +20,8 @@ pluginManagement { // See https://github.com/flutter/flutter/blob/master/docs/ecosystem/Plugins-and-Packages-repository-structure.md#gradle-structure for more info. plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" - id("com.android.application") version "8.11.1" apply false - id("org.jetbrains.kotlin.android") version "2.2.20" apply false + id("com.android.application") version "9.1.0" apply false + id("org.jetbrains.kotlin.android") version "2.4.0" apply false id("com.google.cloud.artifactregistry.gradle-plugin") version "2.2.1" } From 2f0648b75ae9e767f3b94434ce2f6c4ba7e218a9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 12:49:38 -0400 Subject: [PATCH 362/398] remove android underscores --- .../cross_file/example/android/app/build.gradle.kts | 4 ++-- .../MainActivityTest.kt | 2 +- .../example/android/app/src/debug/AndroidManifest.xml | 2 +- .../DriverExtensionActivity.kt | 2 +- .../{cross_file_example => crossfileexample}/MainActivity.kt | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/{cross_file_example => crossfileexample}/MainActivityTest.kt (91%) rename packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/{cross_file_example => crossfileexample}/DriverExtensionActivity.kt (87%) rename packages/cross_file/cross_file/example/android/app/src/main/kotlin/dev/flutter/packages/{cross_file_example => crossfileexample}/MainActivity.kt (83%) diff --git a/packages/cross_file/cross_file/example/android/app/build.gradle.kts b/packages/cross_file/cross_file/example/android/app/build.gradle.kts index 1983fa252654..abe36f89b480 100644 --- a/packages/cross_file/cross_file/example/android/app/build.gradle.kts +++ b/packages/cross_file/cross_file/example/android/app/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } android { - namespace = "dev.flutter.packages.cross_file_example" + namespace = "dev.flutter.packages.crossfileexample" compileSdk = flutter.compileSdkVersion ndkVersion = flutter.ndkVersion @@ -14,7 +14,7 @@ android { } defaultConfig { - applicationId = "dev.flutter.packages.cross_file_example" + applicationId = "dev.flutter.packages.crossfileexample" minSdk = flutter.minSdkVersion targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode diff --git a/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt b/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/crossfileexample/MainActivityTest.kt similarity index 91% rename from packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt rename to packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/crossfileexample/MainActivityTest.kt index 9599b8066aa1..554a7a71b7bb 100644 --- a/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/cross_file_example/MainActivityTest.kt +++ b/packages/cross_file/cross_file/example/android/app/src/androidTest/kotlin/dev/flutter/packages/crossfileexample/MainActivityTest.kt @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package dev.flutter.packages.cross_file_example +package dev.flutter.packages.crossfileexample import androidx.test.rule.ActivityTestRule import dev.flutter.plugins.integration_test.FlutterTestRunner diff --git a/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml b/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml index 527a074bc780..0bde61861589 100644 --- a/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml +++ b/packages/cross_file/cross_file/example/android/app/src/debug/AndroidManifest.xml @@ -6,7 +6,7 @@ Date: Mon, 3 Aug 2026 13:00:01 -0400 Subject: [PATCH 363/398] remove entity export --- .../cross_file_android/lib/cross_file_android.dart | 3 +-- .../cross_file/cross_file_darwin/lib/cross_file_darwin.dart | 3 +-- packages/cross_file/cross_file_io/lib/cross_file_io.dart | 6 +++--- packages/cross_file/cross_file_web/lib/cross_file_web.dart | 3 +-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index c8b851140d17..94345d9ccbdb 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -6,7 +6,6 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams, - PlatformXEntity; + PlatformScopedStorageXFileCreationParams; export 'src/cross_file_android.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 6c2deb751b80..1a62385f9fc9 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -6,8 +6,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams, - PlatformXEntity; + PlatformScopedStorageXFileCreationParams; export 'src/cross_file_darwin.dart'; export 'src/darwin_scoped_storage_cross_directory.dart' diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 62e105c08252..7b9795bcbfec 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -3,8 +3,8 @@ // found in the LICENSE file. export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show ListParams, PlatformXDirectoryCreationParams, PlatformXEntity, PlatformXFileCreationParams; + show ListParams, PlatformXDirectoryCreationParams, PlatformXFileCreationParams; export 'src/cross_file_io.dart'; -export 'src/io_cross_directory.dart' show IOXDirectoryExtension; -export 'src/io_cross_file.dart' show IOXFileExtension; +export 'src/io_cross_directory.dart' show IOXDirectoryCreationParams, IOXDirectoryExtension; +export 'src/io_cross_file.dart' show IOXFileCreationParams, IOXFileExtension; diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index dd9941a3a984..4d8770337dad 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -6,8 +6,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams, - PlatformXEntity; + PlatformScopedStorageXFileCreationParams; export 'src/cross_file_web.dart'; export 'src/web_scoped_storage_cross_file.dart' From 51c46576f70405c753a0efdb3592b8fc22c9b57d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:01:37 -0400 Subject: [PATCH 364/398] change to app facing package wrapper --- packages/cross_file/cross_file/README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index e879d3b1f1cf..90dd9f9b3cea 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -74,15 +74,16 @@ Below is an example of using additional iOS/macOS and Web features for a `XFile` ```dart late final XFile file; -if (CrossFileWeb.isCurrentImplementation()) { - final params = WebScopedStorageXFileCreationParams.fromObjectUrl( - objectUrl: 'blob:https://some/url:for/file', - ); - file = XFile.fromCreationParams(params); -} else if (CrossFileDarwin.isCurrentImplementation()) { - file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); -} else { - file = XFile.fromUri(Uri.file('/my/file.txt')); +switch (CrossFile.implementation) { + case CrossFileWeb(): + final params = WebScopedStorageXFileCreationParams.fromObjectUrl( + objectUrl: 'blob:https://some/url:for/file', + ); + file = XFile.fromCreationParams(params); + case CrossFileDarwin(): + file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); + default: + file = XFile.fromUri(Uri.file('/my/file.txt')); } await file From b388939cd74494212e6d5d546880ddf5cd3fbab2 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 4 Aug 2026 22:50:44 -0400 Subject: [PATCH 365/398] remove web limitations --- packages/cross_file/cross_file_web/README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/packages/cross_file/cross_file_web/README.md b/packages/cross_file/cross_file_web/README.md index 302ff72262bd..db3d2ecaf03a 100644 --- a/packages/cross_file/cross_file_web/README.md +++ b/packages/cross_file/cross_file_web/README.md @@ -11,17 +11,6 @@ so you do not need to add it to your `pubspec.yaml`. However, if you `import` this package to use any of its APIs directly, you should add it to your `pubspec.yaml` as usual. -## Limitations - -`XFile` on the web platform is backed by [Blob](https://api.dart.dev/be/180361/dart-html/Blob-class.html) -objects and their URLs. - -It seems that Safari hangs when reading Blobs larger than 4GB (your app will stop without returning -any data, or throwing an exception). - -This package will attempt to throw an `Exception` before a large file is accessed from Safari (if -its size is known beforehand), so that case can be handled programmatically. - ### Browser compatibility [![Data on Global support for Blob constructing](https://caniuse.bitsofco.de/image/blobbuilder.png)](https://caniuse.com/blobbuilder) From bd3df2ab52d80c34beeb0d35e3844c8d1f7ea310 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 6 Aug 2026 14:06:55 -0400 Subject: [PATCH 366/398] comment about size chosen --- .../lib/src/android_scoped_storage_cross_file.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 7f64941c6480..0159b943f634 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -25,6 +25,10 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { /// InputStream. /// /// Only visible for testing. + /// + /// This can be set to any arbitrary size, but 4KB was chosen because it seems + /// like a good size that balances between minimizing disk size use and + /// minimizing I/O operations. @visibleForTesting static const int maxByteArrayLen = 4 * 1024; From 497ddba73aa8b044d3a1054f8d974c0c62f044c7 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 6 Aug 2026 15:35:08 -0400 Subject: [PATCH 367/398] update ffi --- .../cross_file_darwin_objc/ffi_bindings.g.m | 184 +- .../lib/src/cross_file_darwin.dart | 3 - .../lib/src/ffi_bindings.g.dart | 8191 +++++++++-------- .../cross_file/cross_file_darwin/pubspec.yaml | 2 +- 4 files changed, 4281 insertions(+), 4099 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index 8cc5eb341fa2..afdbd287941b 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -19,15 +19,18 @@ void (*exitIsolate)(void); int64_t (*getMainPortId)(void); bool (*getCurrentThreadOwnsIsolate)(int64_t); + void (*invokeListenerPortBlock)(int64_t port, void*); + void (*invokeBlockingPortBlock)(int64_t port, void*, void*); } DOBJC_Context; id objc_retainBlock(id); -#define BLOCKING_BLOCK_IMPL(ctx, BLOCK_SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ +#define BLOCKING_BLOCK_IMPL(ctx, TYPE, SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ assert(ctx->version >= 1); \ void* targetIsolate = ctx->currentIsolate(); \ int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ - return BLOCK_SIG { \ + __block __weak TYPE weakSelfBlock = nil; \ + TYPE strongSelfBlock = [SIG { \ void* currentIsolate = ctx->currentIsolate(); \ bool mayEnterIsolate = \ currentIsolate == NULL && \ @@ -43,78 +46,167 @@ } \ } else { \ void* waiter = ctx->newWaiter(); \ + TYPE selfRetain = [weakSelfBlock copy]; \ INVOKE_LISTENER; \ ctx->awaitWaiter(waiter); \ + (void)selfRetain; \ } \ - }; + } copy]; \ + weakSelfBlock = strongSelfBlock; \ + return strongSelfBlock; -typedef void (^_ListenerTrampoline)(id arg0, id arg1); +__attribute__((visibility("default"))) +@interface _1w5ousu_BlockArgs_xtuoz7 : NSObject +@property (copy) id block; +@property (strong) id arg0; +@end +@implementation _1w5ousu_BlockArgs_xtuoz7 +@end + +typedef void (^_ListenerTrampoline)(id arg0); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _NativeLibrary_wrapListenerBlock_pfv6jd(_ListenerTrampoline block) NS_RETURNS_RETAINED { - return ^void(id arg0, id arg1) { - objc_retainBlock(block); - block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); - }; +_ListenerTrampoline _1w5ousu_wrapListenerBlock_xtuoz7( + int64_t port, DOBJC_Context* ctx) NS_RETURNS_RETAINED { + __block __weak _ListenerTrampoline weakSelfBlock = nil; + _ListenerTrampoline strongSelfBlock = [^void(id arg0) { + @autoreleasepool { + _1w5ousu_BlockArgs_xtuoz7* args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + ctx->invokeListenerPortBlock(port, (__bridge_retained void*)args); + } + } copy]; + weakSelfBlock = strongSelfBlock; + return strongSelfBlock; } -typedef void (^_BlockingTrampoline)(void * waiter, id arg0, id arg1); +typedef void (^_BlockingTrampoline)(void * waiter, id arg0); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _NativeLibrary_wrapBlockingBlock_pfv6jd( - _BlockingTrampoline block, _BlockingTrampoline listenerBlock, - DOBJC_Context* ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1), { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); +_ListenerTrampoline _1w5ousu_wrapBlockingBlock_xtuoz7(int64_t port, DOBJC_Context* ctx, + void (*directInvoke)(void*)) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, _ListenerTrampoline, ^void(id arg0), { + @autoreleasepool { + _1w5ousu_BlockArgs_xtuoz7* args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + directInvoke((__bridge_retained void*)args); + } }, { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1)); + @autoreleasepool { + _1w5ousu_BlockArgs_xtuoz7* args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + ctx->invokeBlockingPortBlock(port, (__bridge_retained void*)args, waiter); + } }); } +__attribute__((visibility("default"))) +@interface _1w5ousu_BlockArgs_10c3wkj : NSObject +@property (copy) id block; +@property (strong) id arg0; +@property (strong) id arg1; +@property CGImagePropertyOrientation arg2; +@property (strong) id arg3; +@end +@implementation _1w5ousu_BlockArgs_10c3wkj +@end + typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _NativeLibrary_wrapListenerBlock_10c3wkj(_ListenerTrampoline_1 block) NS_RETURNS_RETAINED { - return ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { - objc_retainBlock(block); - block((__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); - }; +_ListenerTrampoline_1 _1w5ousu_wrapListenerBlock_10c3wkj( + int64_t port, DOBJC_Context* ctx) NS_RETURNS_RETAINED { + __block __weak _ListenerTrampoline_1 weakSelfBlock = nil; + _ListenerTrampoline_1 strongSelfBlock = [^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { + @autoreleasepool { + _1w5ousu_BlockArgs_10c3wkj* args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + args.arg2 = arg2; + args.arg3 = arg3; + ctx->invokeListenerPortBlock(port, (__bridge_retained void*)args); + } + } copy]; + weakSelfBlock = strongSelfBlock; + return strongSelfBlock; } typedef void (^_BlockingTrampoline_1)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _NativeLibrary_wrapBlockingBlock_10c3wkj( - _BlockingTrampoline_1 block, _BlockingTrampoline_1 listenerBlock, - DOBJC_Context* ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); +_ListenerTrampoline_1 _1w5ousu_wrapBlockingBlock_10c3wkj(int64_t port, DOBJC_Context* ctx, + void (*directInvoke)(void*)) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, _ListenerTrampoline_1, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { + @autoreleasepool { + _1w5ousu_BlockArgs_10c3wkj* args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + args.arg2 = arg2; + args.arg3 = arg3; + directInvoke((__bridge_retained void*)args); + } }, { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0), (__bridge id)(__bridge_retained void*)(arg1), arg2, (__bridge id)(__bridge_retained void*)(arg3)); + @autoreleasepool { + _1w5ousu_BlockArgs_10c3wkj* args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + args.arg2 = arg2; + args.arg3 = arg3; + ctx->invokeBlockingPortBlock(port, (__bridge_retained void*)args, waiter); + } }); } -typedef void (^_ListenerTrampoline_2)(id arg0); +__attribute__((visibility("default"))) +@interface _1w5ousu_BlockArgs_pfv6jd : NSObject +@property (copy) id block; +@property (strong) id arg0; +@property (strong) id arg1; +@end +@implementation _1w5ousu_BlockArgs_pfv6jd +@end + +typedef void (^_ListenerTrampoline_2)(id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _NativeLibrary_wrapListenerBlock_xtuoz7(_ListenerTrampoline_2 block) NS_RETURNS_RETAINED { - return ^void(id arg0) { - objc_retainBlock(block); - block((__bridge id)(__bridge_retained void*)(arg0)); - }; +_ListenerTrampoline_2 _1w5ousu_wrapListenerBlock_pfv6jd( + int64_t port, DOBJC_Context* ctx) NS_RETURNS_RETAINED { + __block __weak _ListenerTrampoline_2 weakSelfBlock = nil; + _ListenerTrampoline_2 strongSelfBlock = [^void(id arg0, id arg1) { + @autoreleasepool { + _1w5ousu_BlockArgs_pfv6jd* args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + ctx->invokeListenerPortBlock(port, (__bridge_retained void*)args); + } + } copy]; + weakSelfBlock = strongSelfBlock; + return strongSelfBlock; } -typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0); +typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0, id arg1); __attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _NativeLibrary_wrapBlockingBlock_xtuoz7( - _BlockingTrampoline_2 block, _BlockingTrampoline_2 listenerBlock, - DOBJC_Context* ctx) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, ^void(id arg0), { - objc_retainBlock(block); - block(nil, (__bridge id)(__bridge_retained void*)(arg0)); +_ListenerTrampoline_2 _1w5ousu_wrapBlockingBlock_pfv6jd(int64_t port, DOBJC_Context* ctx, + void (*directInvoke)(void*)) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL(ctx, _ListenerTrampoline_2, ^void(id arg0, id arg1), { + @autoreleasepool { + _1w5ousu_BlockArgs_pfv6jd* args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + directInvoke((__bridge_retained void*)args); + } }, { - objc_retainBlock(listenerBlock); - listenerBlock(waiter, (__bridge id)(__bridge_retained void*)(arg0)); + @autoreleasepool { + _1w5ousu_BlockArgs_pfv6jd* args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + ctx->invokeBlockingPortBlock(port, (__bridge_retained void*)args, waiter); + } }); } #undef BLOCKING_BLOCK_IMPL diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index 2895499b9071..f00f2dc02852 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:ffi' as ffi; - import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -15,7 +13,6 @@ base class CrossFileDarwin extends CrossFileIO { /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileDarwin(); - ffi.DynamicLibrary.open('/System/Library/Frameworks/Photos.framework/Photos'); } @override diff --git a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart index 4aa8896313dd..1358cea2becc 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/ffi_bindings.g.dart @@ -4,1206 +4,947 @@ // AUTO GENERATED FILE, DO NOT EDIT. // // Generated by `package:ffigen`. -// ignore_for_file: type=lint, unused_import +// ignore_for_file: type=lint, unused_import, unused_element, deprecated_member_use_from_same_package import 'dart:ffi' as ffi; import 'package:objective_c/objective_c.dart' as objc; import 'package:ffi/ffi.dart' as pkg_ffi; -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer _NativeLibrary_wrapListenerBlock_pfv6jd( - ffi.Pointer block, -); - +const _$objcVersionCheck = objc.ObjCVersionCheck(9, 5); @ffi.Native< ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, + ffi.Int64, ffi.Pointer, + ffi.Pointer args)>>, ) >(isLeaf: true) -external ffi.Pointer _NativeLibrary_wrapBlockingBlock_pfv6jd( - ffi.Pointer block, - ffi.Pointer listnerBlock, +external ffi.Pointer _1w5ousu_wrapBlockingBlock_10c3wkj( + int port, ffi.Pointer context, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer _NativeLibrary_wrapListenerBlock_10c3wkj( - ffi.Pointer block, + ffi.Pointer args)>> + directInvoke, ); @ffi.Native< ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, + ffi.Int64, ffi.Pointer, + ffi.Pointer args)>>, ) >(isLeaf: true) -external ffi.Pointer _NativeLibrary_wrapBlockingBlock_10c3wkj( - ffi.Pointer block, - ffi.Pointer listnerBlock, +external ffi.Pointer _1w5ousu_wrapBlockingBlock_pfv6jd( + int port, ffi.Pointer context, -); - -@ffi.Native Function(ffi.Pointer)>(isLeaf: true) -external ffi.Pointer _NativeLibrary_wrapListenerBlock_xtuoz7( - ffi.Pointer block, + ffi.Pointer args)>> + directInvoke, ); @ffi.Native< ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, + ffi.Int64, ffi.Pointer, + ffi.Pointer args)>>, ) >(isLeaf: true) -external ffi.Pointer _NativeLibrary_wrapBlockingBlock_xtuoz7( - ffi.Pointer block, - ffi.Pointer listnerBlock, +external ffi.Pointer _1w5ousu_wrapBlockingBlock_xtuoz7( + int port, ffi.Pointer context, + ffi.Pointer args)>> + directInvoke, ); -late final _class_NSObject = objc.getClass("NSObject"); -late final _sel_version = objc.registerName("version"); -final _objc_msgSend_1hz7y9r = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Long Function(ffi.Pointer, ffi.Pointer) - > - >() - .asFunction, ffi.Pointer)>(); -late final _sel_setVersion_ = objc.registerName("setVersion:"); -final _objc_msgSend_4sp4xj = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Long, - ) - > - >() - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, int) - >(); -late final _sel_classForCoder = objc.registerName("classForCoder"); -final _objc_msgSend_151sglz = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_replacementObjectForCoder_ = objc.registerName("replacementObjectForCoder:"); -final _objc_msgSend_1sotr3r = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_awakeAfterUsingCoder_ = objc.registerName("awakeAfterUsingCoder:"); +@ffi.Native Function(ffi.Int64, ffi.Pointer)>( + isLeaf: true, +) +external ffi.Pointer _1w5ousu_wrapListenerBlock_10c3wkj( + int port, + ffi.Pointer context, +); -/// NSCoderMethods -extension NSCoderMethods on objc.NSObject { - /// awakeAfterUsingCoder: - objc.ObjCObject? awakeAfterUsingCoder(objc.NSCoder coder) { +@ffi.Native Function(ffi.Int64, ffi.Pointer)>( + isLeaf: true, +) +external ffi.Pointer _1w5ousu_wrapListenerBlock_pfv6jd( + int port, + ffi.Pointer context, +); + +@ffi.Native Function(ffi.Int64, ffi.Pointer)>( + isLeaf: true, +) +external ffi.Pointer _1w5ousu_wrapListenerBlock_xtuoz7( + int port, + ffi.Pointer context, +); + +enum CGImagePropertyOrientation { + kCGImagePropertyOrientationUp(1), + kCGImagePropertyOrientationUpMirrored(2), + kCGImagePropertyOrientationDown(3), + kCGImagePropertyOrientationDownMirrored(4), + kCGImagePropertyOrientationLeftMirrored(5), + kCGImagePropertyOrientationRight(6), + kCGImagePropertyOrientationRightMirrored(7), + kCGImagePropertyOrientationLeft(8); + + final int value; + const CGImagePropertyOrientation(this.value); + + static CGImagePropertyOrientation fromValue(int value) => switch (value) { + 1 => kCGImagePropertyOrientationUp, + 2 => kCGImagePropertyOrientationUpMirrored, + 3 => kCGImagePropertyOrientationDown, + 4 => kCGImagePropertyOrientationDownMirrored, + 5 => kCGImagePropertyOrientationLeftMirrored, + 6 => kCGImagePropertyOrientationRight, + 7 => kCGImagePropertyOrientationRightMirrored, + 8 => kCGImagePropertyOrientationLeft, + _ => throw ArgumentError('Unknown value for CGImagePropertyOrientation: $value'), + }; +} + +/// CIImageProvider +extension CIImageProvider on objc.NSObject { + /// provideImageData:bytesPerRow:origin::size::userInfo: + void provideImageData( + ffi.Pointer data, { + required int bytesPerRow, + required int origin, + required int unnamed, + required int size, + required int unnamed$1, + objc.ObjCObject? userInfo, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = userInfo?.ref; objc.checkOsVersionInternal( - 'NSObject.awakeAfterUsingCoder:', + 'NSObject.provideImageData:bytesPerRow:origin::size::userInfo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.retainAndReturnPointer(), - _sel_awakeAfterUsingCoder_, - coder.ref.pointer, + _objc_msgSend_haq63t( + _$$ref.pointer, + _sel_provideImageData_bytesPerRow_origin__size__userInfo_, + data, + bytesPerRow, + origin, + unnamed, + size, + unnamed$1, + _$$ref$1?.pointer ?? ffi.nullptr, ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } - /// classForCoder - objc.ObjCObject get classForCoder { + /// provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo: + void provideImageToMTLTexture( + MTLTexture texture, { + required MTLCommandBuffer commandBuffer, + required int originx, + required int originy, + required int width, + required int height, + objc.ObjCObject? userInfo, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = texture.ref; + final _$$ref$2 = commandBuffer.ref; + final _$$ref$3 = userInfo?.ref; objc.checkOsVersionInternal( - 'NSObject.classForCoder', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'NSObject.provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:', + macOS: (false, (26, 0, 0)), + ); + _objc_msgSend_1jjfka7( + _$$ref.pointer, + _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_, + _$$ref$1.pointer, + _$$ref$2.pointer, + originx, + originy, + width, + height, + _$$ref$3?.pointer ?? ffi.nullptr, ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForCoder); - return objc.ObjCObject($ret, retain: true, release: true); } +} - /// replacementObjectForCoder: - objc.ObjCObject? replacementObjectForCoder(objc.NSCoder coder) { +/// Conformance +extension Conformance on UTType { + /// conformsToType: + bool conformsToType(UTType type) { + final _$$ref = object$.ref; + final _$$ref$1 = type.ref; objc.checkOsVersionInternal( - 'NSObject.replacementObjectForCoder:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_replacementObjectForCoder_, - coder.ref.pointer, + 'UTType.conformsToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_conformsToType_, _$$ref$1.pointer); } - /// setVersion: - static void setVersion(int aVersion) { + /// isSubtypeOfType: + bool isSubtypeOfType(UTType type) { + final _$$ref = object$.ref; + final _$$ref$1 = type.ref; objc.checkOsVersionInternal( - 'NSObject.setVersion:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'UTType.isSubtypeOfType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - _objc_msgSend_4sp4xj(_class_NSObject, _sel_setVersion_, aVersion); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_isSubtypeOfType_, _$$ref$1.pointer); } - /// version - static int version() { + /// isSupertypeOfType: + bool isSupertypeOfType(UTType type) { + final _$$ref = object$.ref; + final _$$ref$1 = type.ref; objc.checkOsVersionInternal( - 'NSObject.version', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'UTType.isSupertypeOfType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - return _objc_msgSend_1hz7y9r(_class_NSObject, _sel_version); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_isSupertypeOfType_, _$$ref$1.pointer); } -} - -late final _sel_poseAsClass_ = objc.registerName("poseAsClass:"); -final _objc_msgSend_xtuoz7 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -/// NSDeprecatedMethods -extension NSDeprecatedMethods on objc.NSObject { - /// poseAsClass: - static void poseAsClass(objc.ObjCObject aClass) { + /// supertypes + objc.NSSet get supertypes { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.poseAsClass:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'UTType.supertypes', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - _objc_msgSend_xtuoz7(_class_NSObject, _sel_poseAsClass_, aClass.ref.pointer); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_supertypes); + return objc.NSSet.fromPointer($ret, retain: true, release: true); } } -late final _sel_autoContentAccessingProxy = objc.registerName("autoContentAccessingProxy"); +/// LocalConstants +extension LocalConstants on UTType { + /// exportedTypeWithIdentifier: + static UTType exportedTypeWithIdentifier(objc.NSString identifier) { + final _$$ref = identifier.ref; + objc.checkOsVersionInternal( + 'UTType.exportedTypeWithIdentifier:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _class_UTType, + _sel_exportedTypeWithIdentifier_, + _$$ref.pointer, + ); + return UTType.fromPointer($ret, retain: true, release: true); + } -/// NSDiscardableContentProxy -extension NSDiscardableContentProxy on objc.NSObject { - /// autoContentAccessingProxy - objc.ObjCObject get autoContentAccessingProxy { + /// exportedTypeWithIdentifier:conformingToType: + static UTType exportedTypeWithIdentifier$1( + objc.NSString identifier, { + required UTType conformingToType, + }) { + final _$$ref = identifier.ref; + final _$$ref$1 = conformingToType.ref; objc.checkOsVersionInternal( - 'NSObject.autoContentAccessingProxy', - iOS: (false, (4, 0, 0)), - macOS: (false, (10, 6, 0)), + 'UTType.exportedTypeWithIdentifier:conformingToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_autoContentAccessingProxy); - return objc.ObjCObject($ret, retain: true, release: true); + final $ret = _objc_msgSend_15qeuct( + _class_UTType, + _sel_exportedTypeWithIdentifier_conformingToType_, + _$$ref.pointer, + _$$ref$1.pointer, + ); + return UTType.fromPointer($ret, retain: true, release: true); } -} -late final _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_ = objc - .registerName("attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:"); -final _objc_msgSend_10txwc9 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_attemptRecoveryFromError_optionIndex_ = objc.registerName( - "attemptRecoveryFromError:optionIndex:", -); -final _objc_msgSend_z7gxsm = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ) - > - >() - .asFunction< - bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ) - >(); - -/// NSErrorRecoveryAttempting -extension NSErrorRecoveryAttempting on objc.NSObject { - /// attemptRecoveryFromError:optionIndex: - bool attemptRecoveryFromError(objc.NSError error, {required int optionIndex}) { + /// importedTypeWithIdentifier: + static UTType importedTypeWithIdentifier(objc.NSString identifier) { + final _$$ref = identifier.ref; objc.checkOsVersionInternal( - 'NSObject.attemptRecoveryFromError:optionIndex:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'UTType.importedTypeWithIdentifier:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - return _objc_msgSend_z7gxsm( - object$.ref.pointer, - _sel_attemptRecoveryFromError_optionIndex_, - error.ref.pointer, - optionIndex, + final $ret = _objc_msgSend_1sotr3r( + _class_UTType, + _sel_importedTypeWithIdentifier_, + _$$ref.pointer, ); + return UTType.fromPointer($ret, retain: true, release: true); } - /// attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo: - void attemptRecoveryFromError$1( - objc.NSError error, { - required int optionIndex, - objc.ObjCObject? delegate, - required ffi.Pointer didRecoverSelector, - required ffi.Pointer contextInfo, + /// importedTypeWithIdentifier:conformingToType: + static UTType importedTypeWithIdentifier$1( + objc.NSString identifier, { + required UTType conformingToType, }) { + final _$$ref = identifier.ref; + final _$$ref$1 = conformingToType.ref; objc.checkOsVersionInternal( - 'NSObject.attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'UTType.importedTypeWithIdentifier:conformingToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - _objc_msgSend_10txwc9( - object$.ref.pointer, - _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_, - error.ref.pointer, - optionIndex, - delegate?.ref.pointer ?? ffi.nullptr, - didRecoverSelector, - contextInfo, + final $ret = _objc_msgSend_15qeuct( + _class_UTType, + _sel_importedTypeWithIdentifier_conformingToType_, + _$$ref.pointer, + _$$ref$1.pointer, ); + return UTType.fromPointer($ret, retain: true, release: true); } } -late final _sel_performSelector_withObject_afterDelay_inModes_ = objc.registerName( - "performSelector:withObject:afterDelay:inModes:", -); -final _objc_msgSend_t8ajot = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Double, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - double, - ffi.Pointer, - ) - >(); -late final _sel_performSelector_withObject_afterDelay_ = objc.registerName( - "performSelector:withObject:afterDelay:", -); -final _objc_msgSend_7ql5kn = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Double, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - double, - ) - >(); -late final _sel_cancelPreviousPerformRequestsWithTarget_selector_object_ = objc.registerName( - "cancelPreviousPerformRequestsWithTarget:selector:object:", -); -final _objc_msgSend_1ygbbzi = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_cancelPreviousPerformRequestsWithTarget_ = objc.registerName( - "cancelPreviousPerformRequestsWithTarget:", -); +/// WARNING: MTLCommandBuffer is a stub. To generate bindings for this class, include +/// MTLCommandBuffer in your config's objc-protocols list. +/// +/// MTLCommandBuffer +extension type MTLCommandBuffer._(objc.ObjCProtocol object$) implements objc.ObjCProtocol { + /// Constructs a [MTLCommandBuffer] that points to the same underlying object as [other]. + MTLCommandBuffer.as(objc.ObjCObject other) : object$ = other; -/// NSDelayedPerforming -extension NSDelayedPerforming on objc.NSObject { - /// performSelector:withObject:afterDelay: - void performSelector( - ffi.Pointer aSelector, { - objc.ObjCObject? withObject, - required double afterDelay, - }) { + /// Constructs a [MTLCommandBuffer] that wraps the given raw object pointer. + MTLCommandBuffer.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); +} + +/// WARNING: MTLTexture is a stub. To generate bindings for this class, include +/// MTLTexture in your config's objc-protocols list. +/// +/// MTLTexture +extension type MTLTexture._(objc.ObjCProtocol object$) implements objc.ObjCProtocol { + /// Constructs a [MTLTexture] that points to the same underlying object as [other]. + MTLTexture.as(objc.ObjCObject other) : object$ = other; + + /// Constructs a [MTLTexture] that wraps the given raw object pointer. + MTLTexture.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); +} + +/// WARNING: NSArchiver is a stub. To generate bindings for this class, include +/// NSArchiver in your config's objc-interfaces list. +/// +/// NSArchiver +@Deprecated('Use NSKeyedArchiver instead') +extension type NSArchiver._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { + /// Constructs a [NSArchiver] that points to the same underlying object as [other]. + NSArchiver.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal('NSArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); + } + + /// Constructs a [NSArchiver] that wraps the given raw object pointer. + NSArchiver.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal('NSArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); + } +} + +/// NSArchiverCallback +extension NSArchiverCallback on objc.NSObject { + /// classForArchiver + objc.ObjCObject? get classForArchiver { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.performSelector:withObject:afterDelay:', + 'NSObject.classForArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_7ql5kn( - object$.ref.pointer, - _sel_performSelector_withObject_afterDelay_, - aSelector, - withObject?.ref.pointer ?? ffi.nullptr, - afterDelay, - ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_classForArchiver); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// performSelector:withObject:afterDelay:inModes: - void performSelector$1( - ffi.Pointer aSelector, { - objc.ObjCObject? withObject, - required double afterDelay, - required objc.NSArray inModes, - }) { + /// replacementObjectForArchiver: + @Deprecated('Deprecated') + objc.ObjCObject? replacementObjectForArchiver(NSArchiver archiver) { + final _$$ref = object$.ref; + final _$$ref$1 = archiver.ref; objc.checkOsVersionInternal( - 'NSObject.performSelector:withObject:afterDelay:inModes:', + 'NSObject.replacementObjectForArchiver:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_t8ajot( - object$.ref.pointer, - _sel_performSelector_withObject_afterDelay_inModes_, - aSelector, - withObject?.ref.pointer ?? ffi.nullptr, - afterDelay, - inModes.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_replacementObjectForArchiver_, + _$$ref$1.pointer, ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } +} - /// cancelPreviousPerformRequestsWithTarget: - static void cancelPreviousPerformRequestsWithTarget(objc.ObjCObject aTarget) { +/// WARNING: NSClassDescription is a stub. To generate bindings for this class, include +/// NSClassDescription in your config's objc-interfaces list. +/// +/// NSClassDescription +extension type NSClassDescription._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSClassDescription] that points to the same underlying object as [other]. + NSClassDescription.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSClassDescription] that wraps the given raw object pointer. + NSClassDescription.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +/// NSClassDescriptionPrimitives +extension NSClassDescriptionPrimitives on objc.NSObject { + /// attributeKeys + objc.NSArray get attributeKeys { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.cancelPreviousPerformRequestsWithTarget:', + 'NSObject.attributeKeys', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - _class_NSObject, - _sel_cancelPreviousPerformRequestsWithTarget_, - aTarget.ref.pointer, - ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_attributeKeys); + return objc.NSArray.fromPointer($ret, retain: true, release: true); } - /// cancelPreviousPerformRequestsWithTarget:selector:object: - static void cancelPreviousPerformRequestsWithTarget$1( - objc.ObjCObject aTarget, { - required ffi.Pointer selector, - objc.ObjCObject? object, - }) { + /// classDescription + NSClassDescription get classDescription { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.cancelPreviousPerformRequestsWithTarget:selector:object:', + 'NSObject.classDescription', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1ygbbzi( - _class_NSObject, - _sel_cancelPreviousPerformRequestsWithTarget_selector_object_, - aTarget.ref.pointer, - selector, - object?.ref.pointer ?? ffi.nullptr, - ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_classDescription); + return NSClassDescription.fromPointer($ret, retain: true, release: true); } -} - -late final _sel_URL_resourceDataDidBecomeAvailable_ = objc.registerName( - "URL:resourceDataDidBecomeAvailable:", -); -final _objc_msgSend_pfv6jd = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_URLResourceDidFinishLoading_ = objc.registerName("URLResourceDidFinishLoading:"); -late final _sel_URLResourceDidCancelLoading_ = objc.registerName("URLResourceDidCancelLoading:"); -late final _sel_URL_resourceDidFailLoadingWithReason_ = objc.registerName( - "URL:resourceDidFailLoadingWithReason:", -); -/// NSURLClient -extension NSURLClient on objc.NSObject { - /// URL:resourceDataDidBecomeAvailable: - void URL(objc.NSURL sender, {required objc.NSData resourceDataDidBecomeAvailable}) { + /// inverseForRelationshipKey: + objc.NSString? inverseForRelationshipKey(objc.NSString relationshipKey) { + final _$$ref = object$.ref; + final _$$ref$1 = relationshipKey.ref; objc.checkOsVersionInternal( - 'NSObject.URL:resourceDataDidBecomeAvailable:', + 'NSObject.inverseForRelationshipKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_URL_resourceDataDidBecomeAvailable_, - sender.ref.pointer, - resourceDataDidBecomeAvailable.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_inverseForRelationshipKey_, + _$$ref$1.pointer, ); + return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); } - /// URL:resourceDidFailLoadingWithReason: - void URL$1(objc.NSURL sender, {required objc.NSString resourceDidFailLoadingWithReason}) { + /// toManyRelationshipKeys + objc.NSArray get toManyRelationshipKeys { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.URL:resourceDidFailLoadingWithReason:', + 'NSObject.toManyRelationshipKeys', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_URL_resourceDidFailLoadingWithReason_, - sender.ref.pointer, - resourceDidFailLoadingWithReason.ref.pointer, - ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_toManyRelationshipKeys); + return objc.NSArray.fromPointer($ret, retain: true, release: true); } - /// URLResourceDidCancelLoading: - void URLResourceDidCancelLoading(objc.NSURL sender) { + /// toOneRelationshipKeys + objc.NSArray get toOneRelationshipKeys { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.URLResourceDidCancelLoading:', + 'NSObject.toOneRelationshipKeys', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_URLResourceDidCancelLoading_, - sender.ref.pointer, - ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_toOneRelationshipKeys); + return objc.NSArray.fromPointer($ret, retain: true, release: true); } +} - /// URLResourceDidFinishLoading: - void URLResourceDidFinishLoading(objc.NSURL sender) { +/// NSCoderMethods +extension NSCoderMethods on objc.NSObject { + /// awakeAfterUsingCoder: + objc.ObjCObject? awakeAfterUsingCoder(objc.NSCoder coder) { + final _$$ref = object$.ref; + final _$$ref$1 = coder.ref; objc.checkOsVersionInternal( - 'NSObject.URLResourceDidFinishLoading:', + 'NSObject.awakeAfterUsingCoder:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_URLResourceDidFinishLoading_, - sender.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.retainAndReturnPointer(), + _sel_awakeAfterUsingCoder_, + _$$ref$1.pointer, ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } -} - -late final _class_NSFileManager = objc.getClass("NSFileManager"); -late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:"); -final _objc_msgSend_19nvye5 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_defaultManager = objc.registerName("defaultManager"); -late final _sel_isReadableFileAtPath_ = objc.registerName("isReadableFileAtPath:"); -late final _sel_homeDirectoryForCurrentUser = objc.registerName("homeDirectoryForCurrentUser"); -late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); -late final _sel_homeDirectoryForUser_ = objc.registerName("homeDirectoryForUser:"); -/// NSUserInformation -extension NSUserInformation on NSFileManager { - /// homeDirectoryForCurrentUser - objc.NSURL get homeDirectoryForCurrentUser { + /// classForCoder + objc.ObjCObject get classForCoder { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSFileManager.homeDirectoryForCurrentUser', - iOS: (true, null), - macOS: (false, (10, 12, 0)), + 'NSObject.classForCoder', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_homeDirectoryForCurrentUser); - return objc.NSURL.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_classForCoder); + return objc.ObjCObject($ret, retain: true, release: true); } - /// homeDirectoryForUser: - objc.NSURL? homeDirectoryForUser(objc.NSString userName) { + /// replacementObjectForCoder: + objc.ObjCObject? replacementObjectForCoder(objc.NSCoder coder) { + final _$$ref = object$.ref; + final _$$ref$1 = coder.ref; objc.checkOsVersionInternal( - 'NSFileManager.homeDirectoryForUser:', - iOS: (true, null), - macOS: (false, (10, 12, 0)), + 'NSObject.replacementObjectForCoder:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_homeDirectoryForUser_, - userName.ref.pointer, + _$$ref.pointer, + _sel_replacementObjectForCoder_, + _$$ref$1.pointer, ); - return $ret.address == 0 ? null : objc.NSURL.fromPointer($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// temporaryDirectory - objc.NSURL get temporaryDirectory { + /// setVersion: + static void setVersion(int aVersion) { objc.checkOsVersionInternal( - 'NSFileManager.temporaryDirectory', - iOS: (false, (10, 0, 0)), - macOS: (false, (10, 12, 0)), + 'NSObject.setVersion:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_temporaryDirectory); - return objc.NSURL.fromPointer($ret, retain: true, release: true); + _objc_msgSend_4sp4xj(_class_NSObject, _sel_setVersion_, aVersion); } -} -/// NSFileManager -extension type NSFileManager._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { - /// Constructs a [NSFileManager] that points to the same underlying object as [other]. - NSFileManager.as(objc.ObjCObject other) : object$ = other { - assert(isA(object$)); + /// version + static int version() { + objc.checkOsVersionInternal( + 'NSObject.version', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_1hz7y9r(_class_NSObject, _sel_version); } +} - /// Constructs a [NSFileManager] that wraps the given raw object pointer. - NSFileManager.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - assert(isA(object$)); +/// NSComparisonMethods +extension NSComparisonMethods on objc.NSObject { + /// doesContain: + bool doesContain(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; + objc.checkOsVersionInternal( + 'NSObject.doesContain:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_doesContain_, _$$ref$1.pointer); } - /// Returns whether [obj] is an instance of [NSFileManager]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_NSFileManager); - - /// defaultManager - static NSFileManager getDefaultManager() { - final $ret = _objc_msgSend_151sglz(_class_NSFileManager, _sel_defaultManager); - return NSFileManager.fromPointer($ret, retain: true, release: true); + /// isCaseInsensitiveLike: + bool isCaseInsensitiveLike(objc.NSString object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; + objc.checkOsVersionInternal( + 'NSObject.isCaseInsensitiveLike:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_isCaseInsensitiveLike_, _$$ref$1.pointer); } -} -extension NSFileManager$Methods on NSFileManager { - /// isReadableFileAtPath: - bool isReadableFileAtPath(objc.NSString path) { - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isReadableFileAtPath_, path.ref.pointer); + /// isEqualTo: + bool isEqualTo(objc.ObjCObject? object) { + final _$$ref = object$.ref; + final _$$ref$1 = object?.ref; + objc.checkOsVersionInternal( + 'NSObject.isEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_isEqualTo_, _$$ref$1?.pointer ?? ffi.nullptr); } -} -late final _sel_fileManager_shouldProceedAfterError_ = objc.registerName( - "fileManager:shouldProceedAfterError:", -); -final _objc_msgSend_1lsax7n = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_fileManager_willProcessPath_ = objc.registerName("fileManager:willProcessPath:"); - -/// NSCopyLinkMoveHandler -extension NSCopyLinkMoveHandler on objc.NSObject { - /// fileManager:shouldProceedAfterError: - bool fileManager(NSFileManager fm, {required objc.NSDictionary shouldProceedAfterError}) { + /// isGreaterThan: + bool isGreaterThan(objc.ObjCObject? object) { + final _$$ref = object$.ref; + final _$$ref$1 = object?.ref; objc.checkOsVersionInternal( - 'NSObject.fileManager:shouldProceedAfterError:', + 'NSObject.isGreaterThan:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_1lsax7n( - object$.ref.pointer, - _sel_fileManager_shouldProceedAfterError_, - fm.ref.pointer, - shouldProceedAfterError.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_isGreaterThan_, + _$$ref$1?.pointer ?? ffi.nullptr, ); } - /// fileManager:willProcessPath: - void fileManager$1(NSFileManager fm, {required objc.NSString willProcessPath}) { + /// isGreaterThanOrEqualTo: + bool isGreaterThanOrEqualTo(objc.ObjCObject? object) { + final _$$ref = object$.ref; + final _$$ref$1 = object?.ref; objc.checkOsVersionInternal( - 'NSObject.fileManager:willProcessPath:', + 'NSObject.isGreaterThanOrEqualTo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_fileManager_willProcessPath_, - fm.ref.pointer, - willProcessPath.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_isGreaterThanOrEqualTo_, + _$$ref$1?.pointer ?? ffi.nullptr, ); } -} - -late final _sel_accessInstanceVariablesDirectly = objc.registerName( - "accessInstanceVariablesDirectly", -); -final _objc_msgSend_91o635 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Bool Function(ffi.Pointer, ffi.Pointer) - > - >() - .asFunction, ffi.Pointer)>(); -late final _sel_valueForKey_ = objc.registerName("valueForKey:"); -late final _sel_setValue_forKey_ = objc.registerName("setValue:forKey:"); -late final _sel_validateValue_forKey_error_ = objc.registerName("validateValue:forKey:error:"); -final _objc_msgSend_1j9bhml = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ffi.Pointer, - ffi.Pointer>, - ) - > - >() - .asFunction< - bool Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer>, - ffi.Pointer, - ffi.Pointer>, - ) - >(); -late final _sel_mutableArrayValueForKey_ = objc.registerName("mutableArrayValueForKey:"); -late final _sel_mutableOrderedSetValueForKey_ = objc.registerName("mutableOrderedSetValueForKey:"); -late final _sel_mutableSetValueForKey_ = objc.registerName("mutableSetValueForKey:"); -late final _sel_valueForKeyPath_ = objc.registerName("valueForKeyPath:"); -late final _sel_setValue_forKeyPath_ = objc.registerName("setValue:forKeyPath:"); -late final _sel_validateValue_forKeyPath_error_ = objc.registerName( - "validateValue:forKeyPath:error:", -); -late final _sel_mutableArrayValueForKeyPath_ = objc.registerName("mutableArrayValueForKeyPath:"); -late final _sel_mutableOrderedSetValueForKeyPath_ = objc.registerName( - "mutableOrderedSetValueForKeyPath:", -); -late final _sel_mutableSetValueForKeyPath_ = objc.registerName("mutableSetValueForKeyPath:"); -late final _sel_valueForUndefinedKey_ = objc.registerName("valueForUndefinedKey:"); -late final _sel_setValue_forUndefinedKey_ = objc.registerName("setValue:forUndefinedKey:"); -late final _sel_setNilValueForKey_ = objc.registerName("setNilValueForKey:"); -late final _sel_dictionaryWithValuesForKeys_ = objc.registerName("dictionaryWithValuesForKeys:"); -late final _sel_setValuesForKeysWithDictionary_ = objc.registerName( - "setValuesForKeysWithDictionary:", -); -/// NSKeyValueCoding -extension NSKeyValueCoding on objc.NSObject { - /// dictionaryWithValuesForKeys: - objc.NSDictionary dictionaryWithValuesForKeys(objc.NSArray keys) { + /// isLessThan: + bool isLessThan(objc.ObjCObject? object) { + final _$$ref = object$.ref; + final _$$ref$1 = object?.ref; objc.checkOsVersionInternal( - 'NSObject.dictionaryWithValuesForKeys:', + 'NSObject.isLessThan:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_dictionaryWithValuesForKeys_, - keys.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_isLessThan_, + _$$ref$1?.pointer ?? ffi.nullptr, ); - return objc.NSDictionary.fromPointer($ret, retain: true, release: true); } - /// mutableArrayValueForKey: - objc.NSMutableArray mutableArrayValueForKey(objc.NSString key) { + /// isLessThanOrEqualTo: + bool isLessThanOrEqualTo(objc.ObjCObject? object) { + final _$$ref = object$.ref; + final _$$ref$1 = object?.ref; objc.checkOsVersionInternal( - 'NSObject.mutableArrayValueForKey:', + 'NSObject.isLessThanOrEqualTo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_mutableArrayValueForKey_, - key.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_isLessThanOrEqualTo_, + _$$ref$1?.pointer ?? ffi.nullptr, ); - return objc.NSMutableArray.fromPointer($ret, retain: true, release: true); } - /// mutableArrayValueForKeyPath: - objc.NSMutableArray mutableArrayValueForKeyPath(objc.NSString keyPath) { + /// isLike: + bool isLike(objc.NSString object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.mutableArrayValueForKeyPath:', + 'NSObject.isLike:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_mutableArrayValueForKeyPath_, - keyPath.ref.pointer, - ); - return objc.NSMutableArray.fromPointer($ret, retain: true, release: true); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_isLike_, _$$ref$1.pointer); } - /// mutableOrderedSetValueForKey: - objc.NSMutableOrderedSet mutableOrderedSetValueForKey(objc.NSString key) { + /// isNotEqualTo: + bool isNotEqualTo(objc.ObjCObject? object) { + final _$$ref = object$.ref; + final _$$ref$1 = object?.ref; objc.checkOsVersionInternal( - 'NSObject.mutableOrderedSetValueForKey:', - iOS: (false, (5, 0, 0)), - macOS: (false, (10, 7, 0)), + 'NSObject.isNotEqualTo:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_mutableOrderedSetValueForKey_, - key.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_isNotEqualTo_, + _$$ref$1?.pointer ?? ffi.nullptr, ); - return objc.NSMutableOrderedSet.fromPointer($ret, retain: true, release: true); } +} - /// mutableOrderedSetValueForKeyPath: - objc.NSMutableOrderedSet mutableOrderedSetValueForKeyPath(objc.NSString keyPath) { +/// NSCopyLinkMoveHandler +extension NSCopyLinkMoveHandler on objc.NSObject { + /// fileManager:shouldProceedAfterError: + @Deprecated(' Handler API no longer supported') + bool fileManager(NSFileManager fm, {required objc.NSDictionary shouldProceedAfterError}) { + final _$$ref = object$.ref; + final _$$ref$1 = fm.ref; + final _$$ref$2 = shouldProceedAfterError.ref; objc.checkOsVersionInternal( - 'NSObject.mutableOrderedSetValueForKeyPath:', - iOS: (false, (5, 0, 0)), - macOS: (false, (10, 7, 0)), + 'NSObject.fileManager:shouldProceedAfterError:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_mutableOrderedSetValueForKeyPath_, - keyPath.ref.pointer, + return _objc_msgSend_1lsax7n( + _$$ref.pointer, + _sel_fileManager_shouldProceedAfterError_, + _$$ref$1.pointer, + _$$ref$2.pointer, ); - return objc.NSMutableOrderedSet.fromPointer($ret, retain: true, release: true); } - /// mutableSetValueForKey: - objc.NSMutableSet mutableSetValueForKey(objc.NSString key) { + /// fileManager:willProcessPath: + @Deprecated('Handler API no longer supported') + void fileManager$1(NSFileManager fm, {required objc.NSString willProcessPath}) { + final _$$ref = object$.ref; + final _$$ref$1 = fm.ref; + final _$$ref$2 = willProcessPath.ref; objc.checkOsVersionInternal( - 'NSObject.mutableSetValueForKey:', + 'NSObject.fileManager:willProcessPath:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_mutableSetValueForKey_, - key.ref.pointer, + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_fileManager_willProcessPath_, + _$$ref$1.pointer, + _$$ref$2.pointer, ); - return objc.NSMutableSet.fromPointer($ret, retain: true, release: true); } +} - /// mutableSetValueForKeyPath: - objc.NSMutableSet mutableSetValueForKeyPath(objc.NSString keyPath) { +/// NSDelayedPerforming +extension NSDelayedPerforming on objc.NSObject { + /// performSelector:withObject:afterDelay: + void performSelector( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required double afterDelay, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = withObject?.ref; objc.checkOsVersionInternal( - 'NSObject.mutableSetValueForKeyPath:', + 'NSObject.performSelector:withObject:afterDelay:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_mutableSetValueForKeyPath_, - keyPath.ref.pointer, + _objc_msgSend_7ql5kn( + _$$ref.pointer, + _sel_performSelector_withObject_afterDelay_, + aSelector, + _$$ref$1?.pointer ?? ffi.nullptr, + afterDelay, ); - return objc.NSMutableSet.fromPointer($ret, retain: true, release: true); } - /// setNilValueForKey: - void setNilValueForKey(objc.NSString key) { + /// performSelector:withObject:afterDelay:inModes: + void performSelector$1( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required double afterDelay, + required objc.NSArray inModes, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = withObject?.ref; + final _$$ref$2 = inModes.ref; objc.checkOsVersionInternal( - 'NSObject.setNilValueForKey:', + 'NSObject.performSelector:withObject:afterDelay:inModes:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_setNilValueForKey_, key.ref.pointer); + _objc_msgSend_t8ajot( + _$$ref.pointer, + _sel_performSelector_withObject_afterDelay_inModes_, + aSelector, + _$$ref$1?.pointer ?? ffi.nullptr, + afterDelay, + _$$ref$2.pointer, + ); } - /// setValue:forKey: - void setValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + /// cancelPreviousPerformRequestsWithTarget: + static void cancelPreviousPerformRequestsWithTarget(objc.ObjCObject aTarget) { + final _$$ref = aTarget.ref; objc.checkOsVersionInternal( - 'NSObject.setValue:forKey:', + 'NSObject.cancelPreviousPerformRequestsWithTarget:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_setValue_forKey_, - value?.ref.pointer ?? ffi.nullptr, - forKey.ref.pointer, + _objc_msgSend_xtuoz7( + _class_NSObject, + _sel_cancelPreviousPerformRequestsWithTarget_, + _$$ref.pointer, ); } - /// setValue:forKeyPath: - void setValue$1(objc.ObjCObject? value, {required objc.NSString forKeyPath}) { + /// cancelPreviousPerformRequestsWithTarget:selector:object: + static void cancelPreviousPerformRequestsWithTarget$1( + objc.ObjCObject aTarget, { + required ffi.Pointer selector, + objc.ObjCObject? object, + }) { + final _$$ref = aTarget.ref; + final _$$ref$1 = object?.ref; objc.checkOsVersionInternal( - 'NSObject.setValue:forKeyPath:', + 'NSObject.cancelPreviousPerformRequestsWithTarget:selector:object:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_setValue_forKeyPath_, - value?.ref.pointer ?? ffi.nullptr, - forKeyPath.ref.pointer, + _objc_msgSend_1ygbbzi( + _class_NSObject, + _sel_cancelPreviousPerformRequestsWithTarget_selector_object_, + _$$ref.pointer, + selector, + _$$ref$1?.pointer ?? ffi.nullptr, ); } +} - /// setValue:forUndefinedKey: - void setValue$2(objc.ObjCObject? value, {required objc.NSString forUndefinedKey}) { +/// NSDeprecatedKeyValueCoding +extension NSDeprecatedKeyValueCoding on objc.NSObject { + /// handleQueryWithUnboundKey: + @Deprecated('Legacy KVC API') + objc.ObjCObject? handleQueryWithUnboundKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.setValue:forUndefinedKey:', + 'NSObject.handleQueryWithUnboundKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_setValue_forUndefinedKey_, - value?.ref.pointer ?? ffi.nullptr, - forUndefinedKey.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_handleQueryWithUnboundKey_, + _$$ref$1.pointer, ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// setValuesForKeysWithDictionary: - void setValuesForKeysWithDictionary(objc.NSDictionary keyedValues) { + /// handleTakeValue:forUnboundKey: + @Deprecated('Legacy KVC API') + void handleTakeValue(objc.ObjCObject? value, {required objc.NSString forUnboundKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forUnboundKey.ref; objc.checkOsVersionInternal( - 'NSObject.setValuesForKeysWithDictionary:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_setValuesForKeysWithDictionary_, - keyedValues.ref.pointer, - ); - } - - /// validateValue:forKey:error: - bool validateValue( - ffi.Pointer> ioValue, { - required objc.NSString forKey, - }) { - objc.checkOsVersionInternal( - 'NSObject.validateValue:forKey:error:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $err = pkg_ffi.calloc>(); - try { - final $ret = _objc_msgSend_1j9bhml( - object$.ref.pointer, - _sel_validateValue_forKey_error_, - ioValue, - forKey.ref.pointer, - $err, - ); - objc.NSErrorException.checkErrorPointer($err.value); - return $ret; - } finally { - pkg_ffi.calloc.free($err); - } - } - - /// validateValue:forKeyPath:error: - bool validateValue$1( - ffi.Pointer> ioValue, { - required objc.NSString forKeyPath, - }) { - objc.checkOsVersionInternal( - 'NSObject.validateValue:forKeyPath:error:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $err = pkg_ffi.calloc>(); - try { - final $ret = _objc_msgSend_1j9bhml( - object$.ref.pointer, - _sel_validateValue_forKeyPath_error_, - ioValue, - forKeyPath.ref.pointer, - $err, - ); - objc.NSErrorException.checkErrorPointer($err.value); - return $ret; - } finally { - pkg_ffi.calloc.free($err); - } - } - - /// valueForKey: - objc.ObjCObject? valueForKey(objc.NSString key) { - objc.checkOsVersionInternal( - 'NSObject.valueForKey:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r(object$.ref.pointer, _sel_valueForKey_, key.ref.pointer); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); - } - - /// valueForKeyPath: - objc.ObjCObject? valueForKeyPath(objc.NSString keyPath) { - objc.checkOsVersionInternal( - 'NSObject.valueForKeyPath:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_valueForKeyPath_, - keyPath.ref.pointer, - ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); - } - - /// valueForUndefinedKey: - objc.ObjCObject? valueForUndefinedKey(objc.NSString key) { - objc.checkOsVersionInternal( - 'NSObject.valueForUndefinedKey:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_valueForUndefinedKey_, - key.ref.pointer, - ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); - } - - /// accessInstanceVariablesDirectly - static bool getAccessInstanceVariablesDirectly() { - objc.checkOsVersionInternal( - 'NSObject.accessInstanceVariablesDirectly', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_91o635(_class_NSObject, _sel_accessInstanceVariablesDirectly); - } -} - -late final _sel_useStoredAccessor = objc.registerName("useStoredAccessor"); -late final _sel_storedValueForKey_ = objc.registerName("storedValueForKey:"); -late final _sel_takeStoredValue_forKey_ = objc.registerName("takeStoredValue:forKey:"); -late final _sel_takeValue_forKey_ = objc.registerName("takeValue:forKey:"); -late final _sel_takeValue_forKeyPath_ = objc.registerName("takeValue:forKeyPath:"); -late final _sel_handleQueryWithUnboundKey_ = objc.registerName("handleQueryWithUnboundKey:"); -late final _sel_handleTakeValue_forUnboundKey_ = objc.registerName( - "handleTakeValue:forUnboundKey:", -); -late final _sel_unableToSetNilForKey_ = objc.registerName("unableToSetNilForKey:"); -late final _sel_valuesForKeys_ = objc.registerName("valuesForKeys:"); -late final _sel_takeValuesFromDictionary_ = objc.registerName("takeValuesFromDictionary:"); - -/// NSDeprecatedKeyValueCoding -extension NSDeprecatedKeyValueCoding on objc.NSObject { - /// handleQueryWithUnboundKey: - objc.ObjCObject? handleQueryWithUnboundKey(objc.NSString key) { - objc.checkOsVersionInternal( - 'NSObject.handleQueryWithUnboundKey:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_handleQueryWithUnboundKey_, - key.ref.pointer, - ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); - } - - /// handleTakeValue:forUnboundKey: - void handleTakeValue(objc.ObjCObject? value, {required objc.NSString forUnboundKey}) { - objc.checkOsVersionInternal( - 'NSObject.handleTakeValue:forUnboundKey:', + 'NSObject.handleTakeValue:forUnboundKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); _objc_msgSend_pfv6jd( - object$.ref.pointer, + _$$ref.pointer, _sel_handleTakeValue_forUnboundKey_, - value?.ref.pointer ?? ffi.nullptr, - forUnboundKey.ref.pointer, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } /// storedValueForKey: + @Deprecated('Legacy KVC API') objc.ObjCObject? storedValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( 'NSObject.storedValueForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_storedValueForKey_, - key.ref.pointer, - ); + final $ret = _objc_msgSend_1sotr3r(_$$ref.pointer, _sel_storedValueForKey_, _$$ref$1.pointer); return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// takeStoredValue:forKey: + @Deprecated('Legacy KVC API') void takeStoredValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forKey.ref; objc.checkOsVersionInternal( 'NSObject.takeStoredValue:forKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); _objc_msgSend_pfv6jd( - object$.ref.pointer, + _$$ref.pointer, _sel_takeStoredValue_forKey_, - value?.ref.pointer ?? ffi.nullptr, - forKey.ref.pointer, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } /// takeValue:forKey: + @Deprecated('Legacy KVC API') void takeValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forKey.ref; objc.checkOsVersionInternal( 'NSObject.takeValue:forKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); _objc_msgSend_pfv6jd( - object$.ref.pointer, + _$$ref.pointer, _sel_takeValue_forKey_, - value?.ref.pointer ?? ffi.nullptr, - forKey.ref.pointer, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } /// takeValue:forKeyPath: + @Deprecated('Legacy KVC API') void takeValue$1(objc.ObjCObject? value, {required objc.NSString forKeyPath}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forKeyPath.ref; objc.checkOsVersionInternal( 'NSObject.takeValue:forKeyPath:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); _objc_msgSend_pfv6jd( - object$.ref.pointer, + _$$ref.pointer, _sel_takeValue_forKeyPath_, - value?.ref.pointer ?? ffi.nullptr, - forKeyPath.ref.pointer, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } /// takeValuesFromDictionary: + @Deprecated('Legacy KVC API') void takeValuesFromDictionary(objc.NSDictionary properties) { + final _$$ref = object$.ref; + final _$$ref$1 = properties.ref; objc.checkOsVersionInternal( 'NSObject.takeValuesFromDictionary:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_takeValuesFromDictionary_, - properties.ref.pointer, - ); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_takeValuesFromDictionary_, _$$ref$1.pointer); } /// unableToSetNilForKey: + @Deprecated('Legacy KVC API') void unableToSetNilForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( 'NSObject.unableToSetNilForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_unableToSetNilForKey_, key.ref.pointer); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_unableToSetNilForKey_, _$$ref$1.pointer); } /// valuesForKeys: + @Deprecated('Legacy KVC API') objc.NSDictionary valuesForKeys(objc.NSArray keys) { + final _$$ref = object$.ref; + final _$$ref$1 = keys.ref; objc.checkOsVersionInternal( 'NSObject.valuesForKeys:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r(object$.ref.pointer, _sel_valuesForKeys_, keys.ref.pointer); + final $ret = _objc_msgSend_1sotr3r(_$$ref.pointer, _sel_valuesForKeys_, _$$ref$1.pointer); return objc.NSDictionary.fromPointer($ret, retain: true, release: true); } /// useStoredAccessor + @Deprecated('Legacy KVC API') static bool useStoredAccessor() { objc.checkOsVersionInternal( 'NSObject.useStoredAccessor', @@ -1214,1020 +955,1079 @@ extension NSDeprecatedKeyValueCoding on objc.NSObject { } } -late final _sel_observeValueForKeyPath_ofObject_change_context_ = objc.registerName( - "observeValueForKeyPath:ofObject:change:context:", -); -final _objc_msgSend_1pl4k3n = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); - -/// NSKeyValueObserving -extension NSKeyValueObserving on objc.NSObject { - /// observeValueForKeyPath:ofObject:change:context: - void observeValueForKeyPath( - objc.NSString? keyPath, { - objc.ObjCObject? ofObject, - objc.NSDictionary? change, - required ffi.Pointer context, +/// NSDeprecatedKeyValueObservingCustomization +extension NSDeprecatedKeyValueObservingCustomization on objc.NSObject { + /// setKeys:triggerChangeNotificationsForDependentKey: + @Deprecated('Use +keyPathsForValuesAffectingValueForKey instead') + static void setKeys( + objc.NSArray keys, { + required objc.NSString triggerChangeNotificationsForDependentKey, }) { + final _$$ref = keys.ref; + final _$$ref$1 = triggerChangeNotificationsForDependentKey.ref; objc.checkOsVersionInternal( - 'NSObject.observeValueForKeyPath:ofObject:change:context:', + 'NSObject.setKeys:triggerChangeNotificationsForDependentKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1pl4k3n( - object$.ref.pointer, - _sel_observeValueForKeyPath_ofObject_change_context_, - keyPath?.ref.pointer ?? ffi.nullptr, - ofObject?.ref.pointer ?? ffi.nullptr, - change?.ref.pointer ?? ffi.nullptr, - context, + _objc_msgSend_pfv6jd( + _class_NSObject, + _sel_setKeys_triggerChangeNotificationsForDependentKey_, + _$$ref.pointer, + _$$ref$1.pointer, ); } } -late final _sel_addObserver_forKeyPath_options_context_ = objc.registerName( - "addObserver:forKeyPath:options:context:", -); -final _objc_msgSend_akk2cd = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >(); -late final _sel_removeObserver_forKeyPath_context_ = objc.registerName( - "removeObserver:forKeyPath:context:", -); -final _objc_msgSend_1jed5jl = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_removeObserver_forKeyPath_ = objc.registerName("removeObserver:forKeyPath:"); +/// NSDeprecatedMethods +extension NSDeprecatedMethods on objc.NSObject {} -/// NSKeyValueObserverRegistration -extension NSKeyValueObserverRegistration on objc.NSObject { - /// addObserver:forKeyPath:options:context: - void addObserver( - objc.NSObject observer, { - required objc.NSString forKeyPath, - required int options, - required ffi.Pointer context, - }) { +/// NSDiscardableContentProxy +extension NSDiscardableContentProxy on objc.NSObject { + /// autoContentAccessingProxy + objc.ObjCObject get autoContentAccessingProxy { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.addObserver:forKeyPath:options:context:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - _objc_msgSend_akk2cd( - object$.ref.pointer, - _sel_addObserver_forKeyPath_options_context_, - observer.ref.pointer, - forKeyPath.ref.pointer, - options, - context, + 'NSObject.autoContentAccessingProxy', + iOS: (false, (4, 0, 0)), + macOS: (false, (10, 6, 0)), ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_autoContentAccessingProxy); + return objc.ObjCObject($ret, retain: true, release: true); } +} - /// removeObserver:forKeyPath: - void removeObserver(objc.NSObject observer, {required objc.NSString forKeyPath}) { +/// NSDistributedObjects +extension NSDistributedObjects on objc.NSObject { + /// classForPortCoder + @Deprecated('Use NSXPCConnection instead') + objc.ObjCObject get classForPortCoder { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.removeObserver:forKeyPath:', + 'NSObject.classForPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_removeObserver_forKeyPath_, - observer.ref.pointer, - forKeyPath.ref.pointer, - ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_classForPortCoder); + return objc.ObjCObject($ret, retain: true, release: true); } - /// removeObserver:forKeyPath:context: - void removeObserver$1( - objc.NSObject observer, { - required objc.NSString forKeyPath, - required ffi.Pointer context, - }) { + /// replacementObjectForPortCoder: + @Deprecated('Use NSXPCConnection instead') + objc.ObjCObject? replacementObjectForPortCoder(NSPortCoder coder) { + final _$$ref = object$.ref; + final _$$ref$1 = coder.ref; objc.checkOsVersionInternal( - 'NSObject.removeObserver:forKeyPath:context:', - iOS: (false, (5, 0, 0)), - macOS: (false, (10, 7, 0)), + 'NSObject.replacementObjectForPortCoder:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1jed5jl( - object$.ref.pointer, - _sel_removeObserver_forKeyPath_context_, - observer.ref.pointer, - forKeyPath.ref.pointer, - context, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_replacementObjectForPortCoder_, + _$$ref$1.pointer, ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } } -late final _sel_willChangeValueForKey_ = objc.registerName("willChangeValueForKey:"); -late final _sel_didChangeValueForKey_ = objc.registerName("didChangeValueForKey:"); -late final _sel_willChange_valuesAtIndexes_forKey_ = objc.registerName( - "willChange:valuesAtIndexes:forKey:", -); -final _objc_msgSend_1diehjo = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_didChange_valuesAtIndexes_forKey_ = objc.registerName( - "didChange:valuesAtIndexes:forKey:", -); -late final _sel_willChangeValueForKey_withSetMutation_usingObjects_ = objc.registerName( - "willChangeValueForKey:withSetMutation:usingObjects:", -); -final _objc_msgSend_7w1jp7 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >(); -late final _sel_didChangeValueForKey_withSetMutation_usingObjects_ = objc.registerName( - "didChangeValueForKey:withSetMutation:usingObjects:", -); - -/// NSKeyValueObserverNotification -extension NSKeyValueObserverNotification on objc.NSObject { - /// didChange:valuesAtIndexes:forKey: - void didChange( - objc.NSKeyValueChange changeKind, { - required objc.NSIndexSet valuesAtIndexes, - required objc.NSString forKey, - }) { +/// NSErrorRecoveryAttempting +extension NSErrorRecoveryAttempting on objc.NSObject { + /// attemptRecoveryFromError:optionIndex: + bool attemptRecoveryFromError(objc.NSError error, {required int optionIndex}) { + final _$$ref = object$.ref; + final _$$ref$1 = error.ref; objc.checkOsVersionInternal( - 'NSObject.didChange:valuesAtIndexes:forKey:', + 'NSObject.attemptRecoveryFromError:optionIndex:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1diehjo( - object$.ref.pointer, - _sel_didChange_valuesAtIndexes_forKey_, - changeKind.value, - valuesAtIndexes.ref.pointer, - forKey.ref.pointer, + return _objc_msgSend_z7gxsm( + _$$ref.pointer, + _sel_attemptRecoveryFromError_optionIndex_, + _$$ref$1.pointer, + optionIndex, ); } - /// didChangeValueForKey: - void didChangeValueForKey(objc.NSString key) { + /// attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo: + void attemptRecoveryFromError$1( + objc.NSError error, { + required int optionIndex, + objc.ObjCObject? delegate, + required ffi.Pointer didRecoverSelector, + required ffi.Pointer contextInfo, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = error.ref; + final _$$ref$2 = delegate?.ref; objc.checkOsVersionInternal( - 'NSObject.didChangeValueForKey:', + 'NSObject.attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_didChangeValueForKey_, key.ref.pointer); + _objc_msgSend_10txwc9( + _$$ref.pointer, + _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_, + _$$ref$1.pointer, + optionIndex, + _$$ref$2?.pointer ?? ffi.nullptr, + didRecoverSelector, + contextInfo, + ); } +} - /// didChangeValueForKey:withSetMutation:usingObjects: - void didChangeValueForKey$1( - objc.NSString key, { - required objc.NSKeyValueSetMutationKind withSetMutation, - required objc.NSSet usingObjects, - }) { +/// NSFileManager +extension type NSFileManager._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSFileManager] that points to the same underlying object as [other]. + NSFileManager.as(objc.ObjCObject other) : object$ = other { + assert(isA(object$)); + } + + /// Constructs a [NSFileManager] that wraps the given raw object pointer. + NSFileManager.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + assert(isA(object$)); + } + + /// Returns whether [obj] is an instance of [NSFileManager]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_NSFileManager); + + /// defaultManager + static NSFileManager getDefaultManager() { + final $ret = _objc_msgSend_151sglz(_class_NSFileManager, _sel_defaultManager); + return NSFileManager.fromPointer($ret, retain: true, release: true); + } +} + +extension NSFileManager$Methods on NSFileManager { + /// isReadableFileAtPath: + bool isReadableFileAtPath(objc.NSString path) { + final _$$ref = object$.ref; + final _$$ref$1 = path.ref; + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_isReadableFileAtPath_, _$$ref$1.pointer); + } +} + +/// NSKeyValueCoding +extension NSKeyValueCoding on objc.NSObject { + /// dictionaryWithValuesForKeys: + objc.NSDictionary dictionaryWithValuesForKeys(objc.NSArray keys) { + final _$$ref = object$.ref; + final _$$ref$1 = keys.ref; objc.checkOsVersionInternal( - 'NSObject.didChangeValueForKey:withSetMutation:usingObjects:', + 'NSObject.dictionaryWithValuesForKeys:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_7w1jp7( - object$.ref.pointer, - _sel_didChangeValueForKey_withSetMutation_usingObjects_, - key.ref.pointer, - withSetMutation.value, - usingObjects.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_dictionaryWithValuesForKeys_, + _$$ref$1.pointer, ); + return objc.NSDictionary.fromPointer($ret, retain: true, release: true); } - /// willChange:valuesAtIndexes:forKey: - void willChange( - objc.NSKeyValueChange changeKind, { - required objc.NSIndexSet valuesAtIndexes, - required objc.NSString forKey, - }) { + /// mutableArrayValueForKey: + objc.NSMutableArray mutableArrayValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.willChange:valuesAtIndexes:forKey:', + 'NSObject.mutableArrayValueForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1diehjo( - object$.ref.pointer, - _sel_willChange_valuesAtIndexes_forKey_, - changeKind.value, - valuesAtIndexes.ref.pointer, - forKey.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_mutableArrayValueForKey_, + _$$ref$1.pointer, ); + return objc.NSMutableArray.fromPointer($ret, retain: true, release: true); } - /// willChangeValueForKey: - void willChangeValueForKey(objc.NSString key) { + /// mutableArrayValueForKeyPath: + objc.NSMutableArray mutableArrayValueForKeyPath(objc.NSString keyPath) { + final _$$ref = object$.ref; + final _$$ref$1 = keyPath.ref; objc.checkOsVersionInternal( - 'NSObject.willChangeValueForKey:', + 'NSObject.mutableArrayValueForKeyPath:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_xtuoz7(object$.ref.pointer, _sel_willChangeValueForKey_, key.ref.pointer); + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_mutableArrayValueForKeyPath_, + _$$ref$1.pointer, + ); + return objc.NSMutableArray.fromPointer($ret, retain: true, release: true); } - /// willChangeValueForKey:withSetMutation:usingObjects: - void willChangeValueForKey$1( - objc.NSString key, { - required objc.NSKeyValueSetMutationKind withSetMutation, - required objc.NSSet usingObjects, - }) { + /// mutableOrderedSetValueForKey: + objc.NSMutableOrderedSet mutableOrderedSetValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.willChangeValueForKey:withSetMutation:usingObjects:', + 'NSObject.mutableOrderedSetValueForKey:', + iOS: (false, (5, 0, 0)), + macOS: (false, (10, 7, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_mutableOrderedSetValueForKey_, + _$$ref$1.pointer, + ); + return objc.NSMutableOrderedSet.fromPointer($ret, retain: true, release: true); + } + + /// mutableOrderedSetValueForKeyPath: + objc.NSMutableOrderedSet mutableOrderedSetValueForKeyPath(objc.NSString keyPath) { + final _$$ref = object$.ref; + final _$$ref$1 = keyPath.ref; + objc.checkOsVersionInternal( + 'NSObject.mutableOrderedSetValueForKeyPath:', + iOS: (false, (5, 0, 0)), + macOS: (false, (10, 7, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_mutableOrderedSetValueForKeyPath_, + _$$ref$1.pointer, + ); + return objc.NSMutableOrderedSet.fromPointer($ret, retain: true, release: true); + } + + /// mutableSetValueForKey: + objc.NSMutableSet mutableSetValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; + objc.checkOsVersionInternal( + 'NSObject.mutableSetValueForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_7w1jp7( - object$.ref.pointer, - _sel_willChangeValueForKey_withSetMutation_usingObjects_, - key.ref.pointer, - withSetMutation.value, - usingObjects.ref.pointer, + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_mutableSetValueForKey_, + _$$ref$1.pointer, ); + return objc.NSMutableSet.fromPointer($ret, retain: true, release: true); } -} -late final _sel_keyPathsForValuesAffectingValueForKey_ = objc.registerName( - "keyPathsForValuesAffectingValueForKey:", -); -late final _sel_automaticallyNotifiesObserversForKey_ = objc.registerName( - "automaticallyNotifiesObserversForKey:", -); -late final _sel_observationInfo = objc.registerName("observationInfo"); -final _objc_msgSend_6ex6p5 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_setObservationInfo_ = objc.registerName("setObservationInfo:"); -final _objc_msgSend_ovsamd = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); - -/// NSKeyValueObservingCustomization -extension NSKeyValueObservingCustomization on objc.NSObject { - /// observationInfo - ffi.Pointer get observationInfo { + /// mutableSetValueForKeyPath: + objc.NSMutableSet mutableSetValueForKeyPath(objc.NSString keyPath) { + final _$$ref = object$.ref; + final _$$ref$1 = keyPath.ref; objc.checkOsVersionInternal( - 'NSObject.observationInfo', + 'NSObject.mutableSetValueForKeyPath:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_6ex6p5(object$.ref.pointer, _sel_observationInfo); + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_mutableSetValueForKeyPath_, + _$$ref$1.pointer, + ); + return objc.NSMutableSet.fromPointer($ret, retain: true, release: true); } - /// setObservationInfo: - set observationInfo(ffi.Pointer value) { + /// setNilValueForKey: + void setNilValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.setObservationInfo:', + 'NSObject.setNilValueForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_ovsamd(object$.ref.pointer, _sel_setObservationInfo_, value); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_setNilValueForKey_, _$$ref$1.pointer); } - /// automaticallyNotifiesObserversForKey: - static bool automaticallyNotifiesObserversForKey(objc.NSString key) { + /// setValue:forKey: + void setValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forKey.ref; objc.checkOsVersionInternal( - 'NSObject.automaticallyNotifiesObserversForKey:', + 'NSObject.setValue:forKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - _class_NSObject, - _sel_automaticallyNotifiesObserversForKey_, - key.ref.pointer, + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_setValue_forKey_, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } - /// keyPathsForValuesAffectingValueForKey: - static objc.NSSet keyPathsForValuesAffectingValueForKey(objc.NSString key) { + /// setValue:forKeyPath: + void setValue$1(objc.ObjCObject? value, {required objc.NSString forKeyPath}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forKeyPath.ref; objc.checkOsVersionInternal( - 'NSObject.keyPathsForValuesAffectingValueForKey:', + 'NSObject.setValue:forKeyPath:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 5, 0)), + macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - _class_NSObject, - _sel_keyPathsForValuesAffectingValueForKey_, - key.ref.pointer, + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_setValue_forKeyPath_, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); - return objc.NSSet.fromPointer($ret, retain: true, release: true); } -} - -late final _sel_setKeys_triggerChangeNotificationsForDependentKey_ = objc.registerName( - "setKeys:triggerChangeNotificationsForDependentKey:", -); -/// NSDeprecatedKeyValueObservingCustomization -extension NSDeprecatedKeyValueObservingCustomization on objc.NSObject { - /// setKeys:triggerChangeNotificationsForDependentKey: - static void setKeys( - objc.NSArray keys, { - required objc.NSString triggerChangeNotificationsForDependentKey, - }) { + /// setValue:forUndefinedKey: + void setValue$2(objc.ObjCObject? value, {required objc.NSString forUndefinedKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forUndefinedKey.ref; objc.checkOsVersionInternal( - 'NSObject.setKeys:triggerChangeNotificationsForDependentKey:', + 'NSObject.setValue:forUndefinedKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); _objc_msgSend_pfv6jd( - _class_NSObject, - _sel_setKeys_triggerChangeNotificationsForDependentKey_, - keys.ref.pointer, - triggerChangeNotificationsForDependentKey.ref.pointer, + _$$ref.pointer, + _sel_setValue_forUndefinedKey_, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } -} -/// WARNING: NSKeyValueSharedObserversSnapshot is a stub. To generate bindings for this class, include -/// NSKeyValueSharedObserversSnapshot in your config's objc-interfaces list. -/// -/// NSKeyValueSharedObserversSnapshot -extension type NSKeyValueSharedObserversSnapshot._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [NSKeyValueSharedObserversSnapshot] that points to the same underlying object as [other]. - NSKeyValueSharedObserversSnapshot.as(objc.ObjCObject other) : object$ = other { + /// setValuesForKeysWithDictionary: + void setValuesForKeysWithDictionary(objc.NSDictionary keyedValues) { + final _$$ref = object$.ref; + final _$$ref$1 = keyedValues.ref; objc.checkOsVersionInternal( - 'NSKeyValueSharedObserversSnapshot', - iOS: (false, (18, 0, 0)), - macOS: (false, (15, 0, 0)), + 'NSObject.setValuesForKeysWithDictionary:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_setValuesForKeysWithDictionary_, _$$ref$1.pointer); } - /// Constructs a [NSKeyValueSharedObserversSnapshot] that wraps the given raw object pointer. - NSKeyValueSharedObserversSnapshot.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + /// validateValue:forKey:error: + bool validateValue( + ffi.Pointer> ioValue, { + required objc.NSString forKey, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = forKey.ref; objc.checkOsVersionInternal( - 'NSKeyValueSharedObserversSnapshot', - iOS: (false, (18, 0, 0)), - macOS: (false, (15, 0, 0)), + 'NSObject.validateValue:forKey:error:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); + final $err = pkg_ffi.calloc>(); + try { + final $ret = _objc_msgSend_1j9bhml( + _$$ref.pointer, + _sel_validateValue_forKey_error_, + ioValue, + _$$ref$1.pointer, + $err, + ); + objc.NSErrorException.checkErrorPointer($err.value); + return $ret; + } finally { + pkg_ffi.calloc.free($err); + } } -} - -late final _sel_setSharedObservers_ = objc.registerName("setSharedObservers:"); -/// NSKeyValueSharedObserverRegistration -extension NSKeyValueSharedObserverRegistration on objc.NSObject { - /// setSharedObservers: - void setSharedObservers(NSKeyValueSharedObserversSnapshot? sharedObservers) { + /// validateValue:forKeyPath:error: + bool validateValue$1( + ffi.Pointer> ioValue, { + required objc.NSString forKeyPath, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = forKeyPath.ref; objc.checkOsVersionInternal( - 'NSObject.setSharedObservers:', - iOS: (false, (18, 0, 0)), - macOS: (false, (15, 0, 0)), - ); - _objc_msgSend_xtuoz7( - object$.ref.pointer, - _sel_setSharedObservers_, - sharedObservers?.ref.pointer ?? ffi.nullptr, + 'NSObject.validateValue:forKeyPath:error:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), ); + final $err = pkg_ffi.calloc>(); + try { + final $ret = _objc_msgSend_1j9bhml( + _$$ref.pointer, + _sel_validateValue_forKeyPath_error_, + ioValue, + _$$ref$1.pointer, + $err, + ); + objc.NSErrorException.checkErrorPointer($err.value); + return $ret; + } finally { + pkg_ffi.calloc.free($err); + } } -} - -/// WARNING: NSKeyedArchiver is a stub. To generate bindings for this class, include -/// NSKeyedArchiver in your config's objc-interfaces list. -/// -/// NSKeyedArchiver -extension type NSKeyedArchiver._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { - /// Constructs a [NSKeyedArchiver] that points to the same underlying object as [other]. - NSKeyedArchiver.as(objc.ObjCObject other) : object$ = other {} - - /// Constructs a [NSKeyedArchiver] that wraps the given raw object pointer. - NSKeyedArchiver.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} -} -late final _sel_classForKeyedArchiver = objc.registerName("classForKeyedArchiver"); -late final _sel_replacementObjectForKeyedArchiver_ = objc.registerName( - "replacementObjectForKeyedArchiver:", -); -late final _sel_classFallbacksForKeyedArchiver = objc.registerName( - "classFallbacksForKeyedArchiver", -); + /// valueForKey: + objc.ObjCObject? valueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; + objc.checkOsVersionInternal( + 'NSObject.valueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r(_$$ref.pointer, _sel_valueForKey_, _$$ref$1.pointer); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + } -/// NSKeyedArchiverObjectSubstitution -extension NSKeyedArchiverObjectSubstitution on objc.NSObject { - /// classForKeyedArchiver - objc.ObjCObject? get classForKeyedArchiver { + /// valueForKeyPath: + objc.ObjCObject? valueForKeyPath(objc.NSString keyPath) { + final _$$ref = object$.ref; + final _$$ref$1 = keyPath.ref; objc.checkOsVersionInternal( - 'NSObject.classForKeyedArchiver', + 'NSObject.valueForKeyPath:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForKeyedArchiver); + final $ret = _objc_msgSend_1sotr3r(_$$ref.pointer, _sel_valueForKeyPath_, _$$ref$1.pointer); return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// replacementObjectForKeyedArchiver: - objc.ObjCObject? replacementObjectForKeyedArchiver(NSKeyedArchiver archiver) { + /// valueForUndefinedKey: + objc.ObjCObject? valueForUndefinedKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.replacementObjectForKeyedArchiver:', + 'NSObject.valueForUndefinedKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_replacementObjectForKeyedArchiver_, - archiver.ref.pointer, + _$$ref.pointer, + _sel_valueForUndefinedKey_, + _$$ref$1.pointer, ); return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// classFallbacksForKeyedArchiver - static objc.NSArray classFallbacksForKeyedArchiver() { + /// accessInstanceVariablesDirectly + static bool getAccessInstanceVariablesDirectly() { objc.checkOsVersionInternal( - 'NSObject.classFallbacksForKeyedArchiver', + 'NSObject.accessInstanceVariablesDirectly', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(_class_NSObject, _sel_classFallbacksForKeyedArchiver); - return objc.NSArray.fromPointer($ret, retain: true, release: true); + return _objc_msgSend_91o635(_class_NSObject, _sel_accessInstanceVariablesDirectly); } } -late final _sel_classForKeyedUnarchiver = objc.registerName("classForKeyedUnarchiver"); - -/// NSKeyedUnarchiverObjectSubstitution -extension NSKeyedUnarchiverObjectSubstitution on objc.NSObject { - /// classForKeyedUnarchiver - static objc.ObjCObject classForKeyedUnarchiver() { +/// NSKeyValueObserverNotification +extension NSKeyValueObserverNotification on objc.NSObject { + /// didChange:valuesAtIndexes:forKey: + void didChange( + objc.NSKeyValueChange changeKind, { + required objc.NSIndexSet valuesAtIndexes, + required objc.NSString forKey, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = valuesAtIndexes.ref; + final _$$ref$2 = forKey.ref; objc.checkOsVersionInternal( - 'NSObject.classForKeyedUnarchiver', + 'NSObject.didChange:valuesAtIndexes:forKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(_class_NSObject, _sel_classForKeyedUnarchiver); - return objc.ObjCObject($ret, retain: true, release: true); - } -} - -/// WARNING: NSThread is a stub. To generate bindings for this class, include -/// NSThread in your config's objc-interfaces list. -/// -/// NSThread -extension type NSThread._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { - /// Constructs a [NSThread] that points to the same underlying object as [other]. - NSThread.as(objc.ObjCObject other) : object$ = other {} - - /// Constructs a [NSThread] that wraps the given raw object pointer. - NSThread.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} -} - -late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_ = objc.registerName( - "performSelectorOnMainThread:withObject:waitUntilDone:modes:", -); -final _objc_msgSend_1fdou4m = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - bool, - ffi.Pointer, - ) - >(); -late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_ = objc.registerName( - "performSelectorOnMainThread:withObject:waitUntilDone:", -); -final _objc_msgSend_tsocn4 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - bool, - ) - >(); -late final _sel_performSelector_onThread_withObject_waitUntilDone_modes_ = objc.registerName( - "performSelector:onThread:withObject:waitUntilDone:modes:", -); -final _objc_msgSend_1cc1buo = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - bool, - ffi.Pointer, - ) - >(); -late final _sel_performSelector_onThread_withObject_waitUntilDone_ = objc.registerName( - "performSelector:onThread:withObject:waitUntilDone:", -); -final _objc_msgSend_1whyima = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - bool, - ) - >(); -late final _sel_performSelectorInBackground_withObject_ = objc.registerName( - "performSelectorInBackground:withObject:", -); -final _objc_msgSend_1qv0eq4 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); + _objc_msgSend_1diehjo( + _$$ref.pointer, + _sel_didChange_valuesAtIndexes_forKey_, + changeKind.value, + _$$ref$1.pointer, + _$$ref$2.pointer, + ); + } -/// NSThreadPerformAdditions -extension NSThreadPerformAdditions on objc.NSObject { - /// performSelector:onThread:withObject:waitUntilDone: - void performSelector( - ffi.Pointer aSelector, { - required NSThread onThread, - objc.ObjCObject? withObject, - required bool waitUntilDone, - }) { + /// didChangeValueForKey: + void didChangeValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.performSelector:onThread:withObject:waitUntilDone:', + 'NSObject.didChangeValueForKey:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 5, 0)), - ); - _objc_msgSend_1whyima( - object$.ref.pointer, - _sel_performSelector_onThread_withObject_waitUntilDone_, - aSelector, - onThread.ref.pointer, - withObject?.ref.pointer ?? ffi.nullptr, - waitUntilDone, + macOS: (false, (10, 0, 0)), ); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_didChangeValueForKey_, _$$ref$1.pointer); } - /// performSelector:onThread:withObject:waitUntilDone:modes: - void performSelector$1( - ffi.Pointer aSelector, { - required NSThread onThread, - objc.ObjCObject? withObject, - required bool waitUntilDone, - objc.NSArray? modes, + /// didChangeValueForKey:withSetMutation:usingObjects: + void didChangeValueForKey$1( + objc.NSString key, { + required objc.NSKeyValueSetMutationKind withSetMutation, + required objc.NSSet usingObjects, }) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; + final _$$ref$2 = usingObjects.ref; objc.checkOsVersionInternal( - 'NSObject.performSelector:onThread:withObject:waitUntilDone:modes:', + 'NSObject.didChangeValueForKey:withSetMutation:usingObjects:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 5, 0)), + macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1cc1buo( - object$.ref.pointer, - _sel_performSelector_onThread_withObject_waitUntilDone_modes_, - aSelector, - onThread.ref.pointer, - withObject?.ref.pointer ?? ffi.nullptr, - waitUntilDone, - modes?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_7w1jp7( + _$$ref.pointer, + _sel_didChangeValueForKey_withSetMutation_usingObjects_, + _$$ref$1.pointer, + withSetMutation.value, + _$$ref$2.pointer, ); } - /// performSelectorInBackground:withObject: - void performSelectorInBackground( - ffi.Pointer aSelector, { - objc.ObjCObject? withObject, + /// willChange:valuesAtIndexes:forKey: + void willChange( + objc.NSKeyValueChange changeKind, { + required objc.NSIndexSet valuesAtIndexes, + required objc.NSString forKey, }) { + final _$$ref = object$.ref; + final _$$ref$1 = valuesAtIndexes.ref; + final _$$ref$2 = forKey.ref; objc.checkOsVersionInternal( - 'NSObject.performSelectorInBackground:withObject:', + 'NSObject.willChange:valuesAtIndexes:forKey:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 5, 0)), + macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1qv0eq4( - object$.ref.pointer, - _sel_performSelectorInBackground_withObject_, - aSelector, - withObject?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_1diehjo( + _$$ref.pointer, + _sel_willChange_valuesAtIndexes_forKey_, + changeKind.value, + _$$ref$1.pointer, + _$$ref$2.pointer, ); } - /// performSelectorOnMainThread:withObject:waitUntilDone: - void performSelectorOnMainThread( - ffi.Pointer aSelector, { - objc.ObjCObject? withObject, - required bool waitUntilDone, - }) { + /// willChangeValueForKey: + void willChangeValueForKey(objc.NSString key) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; objc.checkOsVersionInternal( - 'NSObject.performSelectorOnMainThread:withObject:waitUntilDone:', + 'NSObject.willChangeValueForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_tsocn4( - object$.ref.pointer, - _sel_performSelectorOnMainThread_withObject_waitUntilDone_, - aSelector, - withObject?.ref.pointer ?? ffi.nullptr, - waitUntilDone, - ); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_willChangeValueForKey_, _$$ref$1.pointer); } - /// performSelectorOnMainThread:withObject:waitUntilDone:modes: - void performSelectorOnMainThread$1( - ffi.Pointer aSelector, { - objc.ObjCObject? withObject, - required bool waitUntilDone, - objc.NSArray? modes, + /// willChangeValueForKey:withSetMutation:usingObjects: + void willChangeValueForKey$1( + objc.NSString key, { + required objc.NSKeyValueSetMutationKind withSetMutation, + required objc.NSSet usingObjects, }) { + final _$$ref = object$.ref; + final _$$ref$1 = key.ref; + final _$$ref$2 = usingObjects.ref; objc.checkOsVersionInternal( - 'NSObject.performSelectorOnMainThread:withObject:waitUntilDone:modes:', + 'NSObject.willChangeValueForKey:withSetMutation:usingObjects:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1fdou4m( - object$.ref.pointer, - _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_, - aSelector, - withObject?.ref.pointer ?? ffi.nullptr, - waitUntilDone, - modes?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_7w1jp7( + _$$ref.pointer, + _sel_willChangeValueForKey_withSetMutation_usingObjects_, + _$$ref$1.pointer, + withSetMutation.value, + _$$ref$2.pointer, ); } } -/// WARNING: NSArchiver is a stub. To generate bindings for this class, include -/// NSArchiver in your config's objc-interfaces list. -/// -/// NSArchiver -extension type NSArchiver._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { - /// Constructs a [NSArchiver] that points to the same underlying object as [other]. - NSArchiver.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal('NSArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); - } - - /// Constructs a [NSArchiver] that wraps the given raw object pointer. - NSArchiver.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal('NSArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); - } -} - -late final _sel_classForArchiver = objc.registerName("classForArchiver"); -late final _sel_replacementObjectForArchiver_ = objc.registerName("replacementObjectForArchiver:"); - -/// NSArchiverCallback -extension NSArchiverCallback on objc.NSObject { - /// classForArchiver - objc.ObjCObject? get classForArchiver { +/// NSKeyValueObserverRegistration +extension NSKeyValueObserverRegistration on objc.NSObject { + /// addObserver:forKeyPath:options:context: + void addObserver( + objc.NSObject observer, { + required objc.NSString forKeyPath, + required int options, + required ffi.Pointer context, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = observer.ref; + final _$$ref$2 = forKeyPath.ref; objc.checkOsVersionInternal( - 'NSObject.classForArchiver', + 'NSObject.addObserver:forKeyPath:options:context:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForArchiver); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + _objc_msgSend_akk2cd( + _$$ref.pointer, + _sel_addObserver_forKeyPath_options_context_, + _$$ref$1.pointer, + _$$ref$2.pointer, + options, + context, + ); } - /// replacementObjectForArchiver: - objc.ObjCObject? replacementObjectForArchiver(NSArchiver archiver) { + /// removeObserver:forKeyPath: + void removeObserver(objc.NSObject observer, {required objc.NSString forKeyPath}) { + final _$$ref = object$.ref; + final _$$ref$1 = observer.ref; + final _$$ref$2 = forKeyPath.ref; objc.checkOsVersionInternal( - 'NSObject.replacementObjectForArchiver:', + 'NSObject.removeObserver:forKeyPath:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_replacementObjectForArchiver_, - archiver.ref.pointer, + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_removeObserver_forKeyPath_, + _$$ref$1.pointer, + _$$ref$2.pointer, ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } -} -/// WARNING: NSPortCoder is a stub. To generate bindings for this class, include -/// NSPortCoder in your config's objc-interfaces list. -/// -/// NSPortCoder -extension type NSPortCoder._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { - /// Constructs a [NSPortCoder] that points to the same underlying object as [other]. - NSPortCoder.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal('NSPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); + /// removeObserver:forKeyPath:context: + void removeObserver$1( + objc.NSObject observer, { + required objc.NSString forKeyPath, + required ffi.Pointer context, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = observer.ref; + final _$$ref$2 = forKeyPath.ref; + objc.checkOsVersionInternal( + 'NSObject.removeObserver:forKeyPath:context:', + iOS: (false, (5, 0, 0)), + macOS: (false, (10, 7, 0)), + ); + _objc_msgSend_1jed5jl( + _$$ref.pointer, + _sel_removeObserver_forKeyPath_context_, + _$$ref$1.pointer, + _$$ref$2.pointer, + context, + ); } +} - /// Constructs a [NSPortCoder] that wraps the given raw object pointer. - NSPortCoder.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal('NSPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); +/// NSKeyValueObserving +extension NSKeyValueObserving on objc.NSObject { + /// observeValueForKeyPath:ofObject:change:context: + void observeValueForKeyPath( + objc.NSString? keyPath, { + objc.ObjCObject? ofObject, + objc.NSDictionary? change, + required ffi.Pointer context, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = keyPath?.ref; + final _$$ref$2 = ofObject?.ref; + final _$$ref$3 = change?.ref; + objc.checkOsVersionInternal( + 'NSObject.observeValueForKeyPath:ofObject:change:context:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1pl4k3n( + _$$ref.pointer, + _sel_observeValueForKeyPath_ofObject_change_context_, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2?.pointer ?? ffi.nullptr, + _$$ref$3?.pointer ?? ffi.nullptr, + context, + ); } } -late final _sel_classForPortCoder = objc.registerName("classForPortCoder"); -late final _sel_replacementObjectForPortCoder_ = objc.registerName( - "replacementObjectForPortCoder:", -); +/// NSKeyValueObservingCustomization +extension NSKeyValueObservingCustomization on objc.NSObject { + /// observationInfo + ffi.Pointer get observationInfo { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'NSObject.observationInfo', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_6ex6p5(_$$ref.pointer, _sel_observationInfo); + } -/// NSDistributedObjects -extension NSDistributedObjects on objc.NSObject { - /// classForPortCoder - objc.ObjCObject get classForPortCoder { + /// setObservationInfo: + set observationInfo(ffi.Pointer value) { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.classForPortCoder', + 'NSObject.setObservationInfo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classForPortCoder); - return objc.ObjCObject($ret, retain: true, release: true); + _objc_msgSend_ovsamd(_$$ref.pointer, _sel_setObservationInfo_, value); } - /// replacementObjectForPortCoder: - objc.ObjCObject? replacementObjectForPortCoder(NSPortCoder coder) { + /// automaticallyNotifiesObserversForKey: + static bool automaticallyNotifiesObserversForKey(objc.NSString key) { + final _$$ref = key.ref; objc.checkOsVersionInternal( - 'NSObject.replacementObjectForPortCoder:', + 'NSObject.automaticallyNotifiesObserversForKey:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); + return _objc_msgSend_19nvye5( + _class_NSObject, + _sel_automaticallyNotifiesObserversForKey_, + _$$ref.pointer, + ); + } + + /// keyPathsForValuesAffectingValueForKey: + static objc.NSSet keyPathsForValuesAffectingValueForKey(objc.NSString key) { + final _$$ref = key.ref; + objc.checkOsVersionInternal( + 'NSObject.keyPathsForValuesAffectingValueForKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 5, 0)), + ); final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_replacementObjectForPortCoder_, - coder.ref.pointer, + _class_NSObject, + _sel_keyPathsForValuesAffectingValueForKey_, + _$$ref.pointer, ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + return objc.NSSet.fromPointer($ret, retain: true, release: true); } } -/// WARNING: NSClassDescription is a stub. To generate bindings for this class, include -/// NSClassDescription in your config's objc-interfaces list. +/// NSKeyValueSharedObserverRegistration +extension NSKeyValueSharedObserverRegistration on objc.NSObject { + /// setSharedObservers: + void setSharedObservers(NSKeyValueSharedObserversSnapshot? sharedObservers) { + final _$$ref = object$.ref; + final _$$ref$1 = sharedObservers?.ref; + objc.checkOsVersionInternal( + 'NSObject.setSharedObservers:', + iOS: (false, (18, 0, 0)), + macOS: (false, (15, 0, 0)), + ); + _objc_msgSend_xtuoz7( + _$$ref.pointer, + _sel_setSharedObservers_, + _$$ref$1?.pointer ?? ffi.nullptr, + ); + } +} + +/// WARNING: NSKeyValueSharedObserversSnapshot is a stub. To generate bindings for this class, include +/// NSKeyValueSharedObserversSnapshot in your config's objc-interfaces list. /// -/// NSClassDescription -extension type NSClassDescription._(objc.ObjCObject object$) +/// NSKeyValueSharedObserversSnapshot +extension type NSKeyValueSharedObserversSnapshot._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { - /// Constructs a [NSClassDescription] that points to the same underlying object as [other]. - NSClassDescription.as(objc.ObjCObject other) : object$ = other {} + /// Constructs a [NSKeyValueSharedObserversSnapshot] that points to the same underlying object as [other]. + NSKeyValueSharedObserversSnapshot.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'NSKeyValueSharedObserversSnapshot', + iOS: (false, (18, 0, 0)), + macOS: (false, (15, 0, 0)), + ); + } - /// Constructs a [NSClassDescription] that wraps the given raw object pointer. - NSClassDescription.fromPointer( + /// Constructs a [NSKeyValueSharedObserversSnapshot] that wraps the given raw object pointer. + NSKeyValueSharedObserversSnapshot.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} -} - -late final _sel_classDescription = objc.registerName("classDescription"); -late final _sel_attributeKeys = objc.registerName("attributeKeys"); -late final _sel_toOneRelationshipKeys = objc.registerName("toOneRelationshipKeys"); -late final _sel_toManyRelationshipKeys = objc.registerName("toManyRelationshipKeys"); -late final _sel_inverseForRelationshipKey_ = objc.registerName("inverseForRelationshipKey:"); - -/// NSClassDescriptionPrimitives -extension NSClassDescriptionPrimitives on objc.NSObject { - /// attributeKeys - objc.NSArray get attributeKeys { + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { objc.checkOsVersionInternal( - 'NSObject.attributeKeys', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'NSKeyValueSharedObserversSnapshot', + iOS: (false, (18, 0, 0)), + macOS: (false, (15, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_attributeKeys); - return objc.NSArray.fromPointer($ret, retain: true, release: true); } +} - /// classDescription - NSClassDescription get classDescription { +/// WARNING: NSKeyedArchiver is a stub. To generate bindings for this class, include +/// NSKeyedArchiver in your config's objc-interfaces list. +/// +/// NSKeyedArchiver +extension type NSKeyedArchiver._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { + /// Constructs a [NSKeyedArchiver] that points to the same underlying object as [other]. + NSKeyedArchiver.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSKeyedArchiver] that wraps the given raw object pointer. + NSKeyedArchiver.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +/// NSKeyedArchiverObjectSubstitution +extension NSKeyedArchiverObjectSubstitution on objc.NSObject { + /// classForKeyedArchiver + objc.ObjCObject? get classForKeyedArchiver { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.classDescription', + 'NSObject.classForKeyedArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_classDescription); - return NSClassDescription.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_classForKeyedArchiver); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// inverseForRelationshipKey: - objc.NSString? inverseForRelationshipKey(objc.NSString relationshipKey) { + /// replacementObjectForKeyedArchiver: + objc.ObjCObject? replacementObjectForKeyedArchiver(NSKeyedArchiver archiver) { + final _$$ref = object$.ref; + final _$$ref$1 = archiver.ref; objc.checkOsVersionInternal( - 'NSObject.inverseForRelationshipKey:', + 'NSObject.replacementObjectForKeyedArchiver:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_inverseForRelationshipKey_, - relationshipKey.ref.pointer, + _$$ref.pointer, + _sel_replacementObjectForKeyedArchiver_, + _$$ref$1.pointer, ); - return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// toManyRelationshipKeys - objc.NSArray get toManyRelationshipKeys { + /// classFallbacksForKeyedArchiver + static objc.NSArray classFallbacksForKeyedArchiver() { objc.checkOsVersionInternal( - 'NSObject.toManyRelationshipKeys', + 'NSObject.classFallbacksForKeyedArchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_toManyRelationshipKeys); + final $ret = _objc_msgSend_151sglz(_class_NSObject, _sel_classFallbacksForKeyedArchiver); return objc.NSArray.fromPointer($ret, retain: true, release: true); } +} - /// toOneRelationshipKeys - objc.NSArray get toOneRelationshipKeys { +/// NSKeyedUnarchiverObjectSubstitution +extension NSKeyedUnarchiverObjectSubstitution on objc.NSObject { + /// classForKeyedUnarchiver + static objc.ObjCObject classForKeyedUnarchiver() { objc.checkOsVersionInternal( - 'NSObject.toOneRelationshipKeys', + 'NSObject.classForKeyedUnarchiver', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_toOneRelationshipKeys); - return objc.NSArray.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(_class_NSObject, _sel_classForKeyedUnarchiver); + return objc.ObjCObject($ret, retain: true, release: true); } } -/// WARNING: NSScriptObjectSpecifier is a stub. To generate bindings for this class, include +/// WARNING: NSPortCoder is a stub. To generate bindings for this class, include +/// NSPortCoder in your config's objc-interfaces list. +/// +/// NSPortCoder +@Deprecated('Use NSXPCConnection instead') +extension type NSPortCoder._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSCoder { + /// Constructs a [NSPortCoder] that points to the same underlying object as [other]. + NSPortCoder.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal('NSPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); + } + + /// Constructs a [NSPortCoder] that wraps the given raw object pointer. + NSPortCoder.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal('NSPortCoder', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0))); + } +} + +/// NSScriptClassDescription +extension NSScriptClassDescription on objc.NSObject { + /// classCode + int get classCode { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'NSObject.classCode', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + return _objc_msgSend_3pyzne(_$$ref.pointer, _sel_classCode); + } + + /// className + objc.NSString get className { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'NSObject.className', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_className); + return objc.NSString.fromPointer($ret, retain: true, release: true); + } +} + +/// NSScriptKeyValueCoding +extension NSScriptKeyValueCoding on objc.NSObject { + /// coerceValue:forKey: + objc.ObjCObject? coerceValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; + final _$$ref$2 = forKey.ref; + objc.checkOsVersionInternal( + 'NSObject.coerceValue:forKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _$$ref.pointer, + _sel_coerceValue_forKey_, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, + ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + } + + /// insertValue:atIndex:inPropertyWithKey: + void insertValue( + objc.ObjCObject value, { + required int atIndex, + required objc.NSString inPropertyWithKey, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = value.ref; + final _$$ref$2 = inPropertyWithKey.ref; + objc.checkOsVersionInternal( + 'NSObject.insertValue:atIndex:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_10nfbmq( + _$$ref.pointer, + _sel_insertValue_atIndex_inPropertyWithKey_, + _$$ref$1.pointer, + atIndex, + _$$ref$2.pointer, + ); + } + + /// insertValue:inPropertyWithKey: + void insertValue$1(objc.ObjCObject value, {required objc.NSString inPropertyWithKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = value.ref; + final _$$ref$2 = inPropertyWithKey.ref; + objc.checkOsVersionInternal( + 'NSObject.insertValue:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_insertValue_inPropertyWithKey_, + _$$ref$1.pointer, + _$$ref$2.pointer, + ); + } + + /// removeValueAtIndex:fromPropertyWithKey: + void removeValueAtIndex(int index, {required objc.NSString fromPropertyWithKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = fromPropertyWithKey.ref; + objc.checkOsVersionInternal( + 'NSObject.removeValueAtIndex:fromPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_1gypgok( + _$$ref.pointer, + _sel_removeValueAtIndex_fromPropertyWithKey_, + index, + _$$ref$1.pointer, + ); + } + + /// replaceValueAtIndex:inPropertyWithKey:withValue: + void replaceValueAtIndex( + int index, { + required objc.NSString inPropertyWithKey, + required objc.ObjCObject withValue, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = inPropertyWithKey.ref; + final _$$ref$2 = withValue.ref; + objc.checkOsVersionInternal( + 'NSObject.replaceValueAtIndex:inPropertyWithKey:withValue:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + _objc_msgSend_rutu22( + _$$ref.pointer, + _sel_replaceValueAtIndex_inPropertyWithKey_withValue_, + index, + _$$ref$1.pointer, + _$$ref$2.pointer, + ); + } + + /// valueAtIndex:inPropertyWithKey: + objc.ObjCObject? valueAtIndex(int index, {required objc.NSString inPropertyWithKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = inPropertyWithKey.ref; + objc.checkOsVersionInternal( + 'NSObject.valueAtIndex:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_vbc8p4( + _$$ref.pointer, + _sel_valueAtIndex_inPropertyWithKey_, + index, + _$$ref$1.pointer, + ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + } + + /// valueWithName:inPropertyWithKey: + objc.ObjCObject? valueWithName(objc.NSString name, {required objc.NSString inPropertyWithKey}) { + final _$$ref = object$.ref; + final _$$ref$1 = name.ref; + final _$$ref$2 = inPropertyWithKey.ref; + objc.checkOsVersionInternal( + 'NSObject.valueWithName:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _$$ref.pointer, + _sel_valueWithName_inPropertyWithKey_, + _$$ref$1.pointer, + _$$ref$2.pointer, + ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + } + + /// valueWithUniqueID:inPropertyWithKey: + objc.ObjCObject? valueWithUniqueID( + objc.ObjCObject uniqueID, { + required objc.NSString inPropertyWithKey, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = uniqueID.ref; + final _$$ref$2 = inPropertyWithKey.ref; + objc.checkOsVersionInternal( + 'NSObject.valueWithUniqueID:inPropertyWithKey:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_15qeuct( + _$$ref.pointer, + _sel_valueWithUniqueID_inPropertyWithKey_, + _$$ref$1.pointer, + _$$ref$2.pointer, + ); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + } +} + +/// WARNING: NSScriptObjectSpecifier is a stub. To generate bindings for this class, include /// NSScriptObjectSpecifier in your config's objc-interfaces list. /// /// NSScriptObjectSpecifier @@ -2244,58 +2044,39 @@ extension type NSScriptObjectSpecifier._(objc.ObjCObject object$) }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} } -late final _sel_scriptingValueForSpecifier_ = objc.registerName("scriptingValueForSpecifier:"); -late final _sel_scriptingProperties = objc.registerName("scriptingProperties"); -late final _sel_setScriptingProperties_ = objc.registerName("setScriptingProperties:"); -late final _sel_copyScriptingValue_forKey_withProperties_ = objc.registerName( - "copyScriptingValue:forKey:withProperties:", -); -final _objc_msgSend_11spmsz = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_ = objc - .registerName("newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:"); -final _objc_msgSend_s92gih = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); +/// NSScriptObjectSpecifiers +extension NSScriptObjectSpecifiers on objc.NSObject { + /// indicesOfObjectsByEvaluatingObjectSpecifier: + objc.NSArray? indicesOfObjectsByEvaluatingObjectSpecifier(NSScriptObjectSpecifier specifier) { + final _$$ref = object$.ref; + final _$$ref$1 = specifier.ref; + objc.checkOsVersionInternal( + 'NSObject.indicesOfObjectsByEvaluatingObjectSpecifier:', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_indicesOfObjectsByEvaluatingObjectSpecifier_, + _$$ref$1.pointer, + ); + return $ret.address == 0 ? null : objc.NSArray.fromPointer($ret, retain: true, release: true); + } + + /// objectSpecifier + NSScriptObjectSpecifier? get objectSpecifier { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'NSObject.objectSpecifier', + iOS: (false, (2, 0, 0)), + macOS: (false, (10, 0, 0)), + ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_objectSpecifier); + return $ret.address == 0 + ? null + : NSScriptObjectSpecifier.fromPointer($ret, retain: true, release: true); + } +} /// NSScripting extension NSScripting on objc.NSObject { @@ -2305,17 +2086,21 @@ extension NSScripting on objc.NSObject { required objc.NSString forKey, required objc.NSDictionary withProperties, }) { + final _$$ref = object$.ref; + final _$$ref$1 = value.ref; + final _$$ref$2 = forKey.ref; + final _$$ref$3 = withProperties.ref; objc.checkOsVersionInternal( 'NSObject.copyScriptingValue:forKey:withProperties:', iOS: (true, null), macOS: (false, (10, 5, 0)), ); final $ret = _objc_msgSend_11spmsz( - object$.ref.pointer, + _$$ref.pointer, _sel_copyScriptingValue_forKey_withProperties_, - value.ref.pointer, - forKey.ref.pointer, - withProperties.ref.pointer, + _$$ref$1.pointer, + _$$ref$2.pointer, + _$$ref$3.pointer, ); return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } @@ -2327,30 +2112,36 @@ extension NSScripting on objc.NSObject { objc.ObjCObject? withContentsValue, required objc.NSDictionary properties, }) { + final _$$ref = object$.ref; + final _$$ref$1 = objectClass.ref; + final _$$ref$2 = forValueForKey.ref; + final _$$ref$3 = withContentsValue?.ref; + final _$$ref$4 = properties.ref; objc.checkOsVersionInternal( 'NSObject.newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:', iOS: (true, null), macOS: (false, (10, 5, 0)), ); final $ret = _objc_msgSend_s92gih( - object$.ref.pointer, + _$$ref.pointer, _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_, - objectClass.ref.pointer, - forValueForKey.ref.pointer, - withContentsValue?.ref.pointer ?? ffi.nullptr, - properties.ref.pointer, + _$$ref$1.pointer, + _$$ref$2.pointer, + _$$ref$3?.pointer ?? ffi.nullptr, + _$$ref$4.pointer, ); return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: false, release: true); } /// scriptingProperties objc.NSDictionary? get scriptingProperties { + final _$$ref = object$.ref; objc.checkOsVersionInternal( 'NSObject.scriptingProperties', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_scriptingProperties); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_scriptingProperties); return $ret.address == 0 ? null : objc.NSDictionary.fromPointer($ret, retain: true, release: true); @@ -2358,933 +2149,635 @@ extension NSScripting on objc.NSObject { /// scriptingValueForSpecifier: objc.ObjCObject? scriptingValueForSpecifier(NSScriptObjectSpecifier objectSpecifier) { + final _$$ref = object$.ref; + final _$$ref$1 = objectSpecifier.ref; objc.checkOsVersionInternal( 'NSObject.scriptingValueForSpecifier:', iOS: (true, null), macOS: (false, (10, 5, 0)), ); final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, + _$$ref.pointer, _sel_scriptingValueForSpecifier_, - objectSpecifier.ref.pointer, + _$$ref$1.pointer, ); return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } /// setScriptingProperties: set scriptingProperties(objc.NSDictionary? value) { + final _$$ref = object$.ref; + final _$$ref$1 = value?.ref; objc.checkOsVersionInternal( 'NSObject.setScriptingProperties:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); _objc_msgSend_xtuoz7( - object$.ref.pointer, + _$$ref.pointer, _sel_setScriptingProperties_, - value?.ref.pointer ?? ffi.nullptr, + _$$ref$1?.pointer ?? ffi.nullptr, ); } } -late final _sel_classCode = objc.registerName("classCode"); -final _objc_msgSend_3pyzne = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.UnsignedInt Function(ffi.Pointer, ffi.Pointer) - > - >() - .asFunction, ffi.Pointer)>(); -late final _sel_className = objc.registerName("className"); - -/// NSScriptClassDescription -extension NSScriptClassDescription on objc.NSObject { - /// classCode - int get classCode { - objc.checkOsVersionInternal( - 'NSObject.classCode', +/// NSScriptingComparisonMethods +extension NSScriptingComparisonMethods on objc.NSObject { + /// scriptingBeginsWith: + bool scriptingBeginsWith(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; + objc.checkOsVersionInternal( + 'NSObject.scriptingBeginsWith:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_3pyzne(object$.ref.pointer, _sel_classCode); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_scriptingBeginsWith_, _$$ref$1.pointer); } - /// className - objc.NSString get className { + /// scriptingContains: + bool scriptingContains(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.className', + 'NSObject.scriptingContains:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_className); - return objc.NSString.fromPointer($ret, retain: true, release: true); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_scriptingContains_, _$$ref$1.pointer); } -} - -late final _sel_valueAtIndex_inPropertyWithKey_ = objc.registerName( - "valueAtIndex:inPropertyWithKey:", -); -final _objc_msgSend_vbc8p4 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >(); -late final _sel_valueWithName_inPropertyWithKey_ = objc.registerName( - "valueWithName:inPropertyWithKey:", -); -final _objc_msgSend_15qeuct = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - ffi.Pointer Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_valueWithUniqueID_inPropertyWithKey_ = objc.registerName( - "valueWithUniqueID:inPropertyWithKey:", -); -late final _sel_insertValue_atIndex_inPropertyWithKey_ = objc.registerName( - "insertValue:atIndex:inPropertyWithKey:", -); -final _objc_msgSend_10nfbmq = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >(); -late final _sel_removeValueAtIndex_fromPropertyWithKey_ = objc.registerName( - "removeValueAtIndex:fromPropertyWithKey:", -); -final _objc_msgSend_1gypgok = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >(); -late final _sel_replaceValueAtIndex_inPropertyWithKey_withValue_ = objc.registerName( - "replaceValueAtIndex:inPropertyWithKey:withValue:", -); -final _objc_msgSend_rutu22 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_insertValue_inPropertyWithKey_ = objc.registerName( - "insertValue:inPropertyWithKey:", -); -late final _sel_coerceValue_forKey_ = objc.registerName("coerceValue:forKey:"); -/// NSScriptKeyValueCoding -extension NSScriptKeyValueCoding on objc.NSObject { - /// coerceValue:forKey: - objc.ObjCObject? coerceValue(objc.ObjCObject? value, {required objc.NSString forKey}) { + /// scriptingEndsWith: + bool scriptingEndsWith(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.coerceValue:forKey:', + 'NSObject.scriptingEndsWith:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_15qeuct( - object$.ref.pointer, - _sel_coerceValue_forKey_, - value?.ref.pointer ?? ffi.nullptr, - forKey.ref.pointer, - ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_scriptingEndsWith_, _$$ref$1.pointer); } - /// insertValue:atIndex:inPropertyWithKey: - void insertValue( - objc.ObjCObject value, { - required int atIndex, - required objc.NSString inPropertyWithKey, - }) { + /// scriptingIsEqualTo: + bool scriptingIsEqualTo(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.insertValue:atIndex:inPropertyWithKey:', + 'NSObject.scriptingIsEqualTo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_10nfbmq( - object$.ref.pointer, - _sel_insertValue_atIndex_inPropertyWithKey_, - value.ref.pointer, - atIndex, - inPropertyWithKey.ref.pointer, - ); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_scriptingIsEqualTo_, _$$ref$1.pointer); } - /// insertValue:inPropertyWithKey: - void insertValue$1(objc.ObjCObject value, {required objc.NSString inPropertyWithKey}) { + /// scriptingIsGreaterThan: + bool scriptingIsGreaterThan(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.insertValue:inPropertyWithKey:', + 'NSObject.scriptingIsGreaterThan:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_pfv6jd( - object$.ref.pointer, - _sel_insertValue_inPropertyWithKey_, - value.ref.pointer, - inPropertyWithKey.ref.pointer, - ); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_scriptingIsGreaterThan_, _$$ref$1.pointer); } - /// removeValueAtIndex:fromPropertyWithKey: - void removeValueAtIndex(int index, {required objc.NSString fromPropertyWithKey}) { + /// scriptingIsGreaterThanOrEqualTo: + bool scriptingIsGreaterThanOrEqualTo(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.removeValueAtIndex:fromPropertyWithKey:', + 'NSObject.scriptingIsGreaterThanOrEqualTo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_1gypgok( - object$.ref.pointer, - _sel_removeValueAtIndex_fromPropertyWithKey_, - index, - fromPropertyWithKey.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_scriptingIsGreaterThanOrEqualTo_, + _$$ref$1.pointer, ); } - /// replaceValueAtIndex:inPropertyWithKey:withValue: - void replaceValueAtIndex( - int index, { - required objc.NSString inPropertyWithKey, - required objc.ObjCObject withValue, - }) { + /// scriptingIsLessThan: + bool scriptingIsLessThan(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.replaceValueAtIndex:inPropertyWithKey:withValue:', + 'NSObject.scriptingIsLessThan:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - _objc_msgSend_rutu22( - object$.ref.pointer, - _sel_replaceValueAtIndex_inPropertyWithKey_withValue_, - index, - inPropertyWithKey.ref.pointer, - withValue.ref.pointer, - ); + return _objc_msgSend_19nvye5(_$$ref.pointer, _sel_scriptingIsLessThan_, _$$ref$1.pointer); } - /// valueAtIndex:inPropertyWithKey: - objc.ObjCObject? valueAtIndex(int index, {required objc.NSString inPropertyWithKey}) { + /// scriptingIsLessThanOrEqualTo: + bool scriptingIsLessThanOrEqualTo(objc.ObjCObject object) { + final _$$ref = object$.ref; + final _$$ref$1 = object.ref; objc.checkOsVersionInternal( - 'NSObject.valueAtIndex:inPropertyWithKey:', + 'NSObject.scriptingIsLessThanOrEqualTo:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - final $ret = _objc_msgSend_vbc8p4( - object$.ref.pointer, - _sel_valueAtIndex_inPropertyWithKey_, - index, - inPropertyWithKey.ref.pointer, + return _objc_msgSend_19nvye5( + _$$ref.pointer, + _sel_scriptingIsLessThanOrEqualTo_, + _$$ref$1.pointer, ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } +} - /// valueWithName:inPropertyWithKey: - objc.ObjCObject? valueWithName(objc.NSString name, {required objc.NSString inPropertyWithKey}) { +/// WARNING: NSThread is a stub. To generate bindings for this class, include +/// NSThread in your config's objc-interfaces list. +/// +/// NSThread +extension type NSThread._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { + /// Constructs a [NSThread] that points to the same underlying object as [other]. + NSThread.as(objc.ObjCObject other) : object$ = other {} + + /// Constructs a [NSThread] that wraps the given raw object pointer. + NSThread.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) {} +} + +/// NSThreadPerformAdditions +extension NSThreadPerformAdditions on objc.NSObject { + /// performSelector:onThread:withObject:waitUntilDone: + void performSelector( + ffi.Pointer aSelector, { + required NSThread onThread, + objc.ObjCObject? withObject, + required bool waitUntilDone, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = onThread.ref; + final _$$ref$2 = withObject?.ref; objc.checkOsVersionInternal( - 'NSObject.valueWithName:inPropertyWithKey:', + 'NSObject.performSelector:onThread:withObject:waitUntilDone:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + macOS: (false, (10, 5, 0)), ); - final $ret = _objc_msgSend_15qeuct( - object$.ref.pointer, - _sel_valueWithName_inPropertyWithKey_, - name.ref.pointer, - inPropertyWithKey.ref.pointer, + _objc_msgSend_1whyima( + _$$ref.pointer, + _sel_performSelector_onThread_withObject_waitUntilDone_, + aSelector, + _$$ref$1.pointer, + _$$ref$2?.pointer ?? ffi.nullptr, + waitUntilDone, ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } - /// valueWithUniqueID:inPropertyWithKey: - objc.ObjCObject? valueWithUniqueID( - objc.ObjCObject uniqueID, { - required objc.NSString inPropertyWithKey, - }) { - objc.checkOsVersionInternal( - 'NSObject.valueWithUniqueID:inPropertyWithKey:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_15qeuct( - object$.ref.pointer, - _sel_valueWithUniqueID_inPropertyWithKey_, - uniqueID.ref.pointer, - inPropertyWithKey.ref.pointer, - ); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); - } -} - -late final _sel_objectSpecifier = objc.registerName("objectSpecifier"); -late final _sel_indicesOfObjectsByEvaluatingObjectSpecifier_ = objc.registerName( - "indicesOfObjectsByEvaluatingObjectSpecifier:", -); - -/// NSScriptObjectSpecifiers -extension NSScriptObjectSpecifiers on objc.NSObject { - /// indicesOfObjectsByEvaluatingObjectSpecifier: - objc.NSArray? indicesOfObjectsByEvaluatingObjectSpecifier(NSScriptObjectSpecifier specifier) { - objc.checkOsVersionInternal( - 'NSObject.indicesOfObjectsByEvaluatingObjectSpecifier:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - object$.ref.pointer, - _sel_indicesOfObjectsByEvaluatingObjectSpecifier_, - specifier.ref.pointer, - ); - return $ret.address == 0 ? null : objc.NSArray.fromPointer($ret, retain: true, release: true); - } - - /// objectSpecifier - NSScriptObjectSpecifier? get objectSpecifier { - objc.checkOsVersionInternal( - 'NSObject.objectSpecifier', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_objectSpecifier); - return $ret.address == 0 - ? null - : NSScriptObjectSpecifier.fromPointer($ret, retain: true, release: true); - } -} - -late final _sel_isEqualTo_ = objc.registerName("isEqualTo:"); -late final _sel_isLessThanOrEqualTo_ = objc.registerName("isLessThanOrEqualTo:"); -late final _sel_isLessThan_ = objc.registerName("isLessThan:"); -late final _sel_isGreaterThanOrEqualTo_ = objc.registerName("isGreaterThanOrEqualTo:"); -late final _sel_isGreaterThan_ = objc.registerName("isGreaterThan:"); -late final _sel_isNotEqualTo_ = objc.registerName("isNotEqualTo:"); -late final _sel_doesContain_ = objc.registerName("doesContain:"); -late final _sel_isLike_ = objc.registerName("isLike:"); -late final _sel_isCaseInsensitiveLike_ = objc.registerName("isCaseInsensitiveLike:"); - -/// NSComparisonMethods -extension NSComparisonMethods on objc.NSObject { - /// doesContain: - bool doesContain(objc.ObjCObject object) { - objc.checkOsVersionInternal( - 'NSObject.doesContain:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_doesContain_, object.ref.pointer); - } - - /// isCaseInsensitiveLike: - bool isCaseInsensitiveLike(objc.NSString object) { + /// performSelector:onThread:withObject:waitUntilDone:modes: + void performSelector$1( + ffi.Pointer aSelector, { + required NSThread onThread, + objc.ObjCObject? withObject, + required bool waitUntilDone, + objc.NSArray? modes, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = onThread.ref; + final _$$ref$2 = withObject?.ref; + final _$$ref$3 = modes?.ref; objc.checkOsVersionInternal( - 'NSObject.isCaseInsensitiveLike:', + 'NSObject.performSelector:onThread:withObject:waitUntilDone:modes:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + macOS: (false, (10, 5, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isCaseInsensitiveLike_, - object.ref.pointer, + _objc_msgSend_1cc1buo( + _$$ref.pointer, + _sel_performSelector_onThread_withObject_waitUntilDone_modes_, + aSelector, + _$$ref$1.pointer, + _$$ref$2?.pointer ?? ffi.nullptr, + waitUntilDone, + _$$ref$3?.pointer ?? ffi.nullptr, ); } - /// isEqualTo: - bool isEqualTo(objc.ObjCObject? object) { + /// performSelectorInBackground:withObject: + void performSelectorInBackground( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = withObject?.ref; objc.checkOsVersionInternal( - 'NSObject.isEqualTo:', + 'NSObject.performSelectorInBackground:withObject:', iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + macOS: (false, (10, 5, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isEqualTo_, - object?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_1qv0eq4( + _$$ref.pointer, + _sel_performSelectorInBackground_withObject_, + aSelector, + _$$ref$1?.pointer ?? ffi.nullptr, ); } - /// isGreaterThan: - bool isGreaterThan(objc.ObjCObject? object) { + /// performSelectorOnMainThread:withObject:waitUntilDone: + void performSelectorOnMainThread( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required bool waitUntilDone, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = withObject?.ref; objc.checkOsVersionInternal( - 'NSObject.isGreaterThan:', + 'NSObject.performSelectorOnMainThread:withObject:waitUntilDone:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isGreaterThan_, - object?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_tsocn4( + _$$ref.pointer, + _sel_performSelectorOnMainThread_withObject_waitUntilDone_, + aSelector, + _$$ref$1?.pointer ?? ffi.nullptr, + waitUntilDone, ); } - /// isGreaterThanOrEqualTo: - bool isGreaterThanOrEqualTo(objc.ObjCObject? object) { + /// performSelectorOnMainThread:withObject:waitUntilDone:modes: + void performSelectorOnMainThread$1( + ffi.Pointer aSelector, { + objc.ObjCObject? withObject, + required bool waitUntilDone, + objc.NSArray? modes, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = withObject?.ref; + final _$$ref$2 = modes?.ref; objc.checkOsVersionInternal( - 'NSObject.isGreaterThanOrEqualTo:', + 'NSObject.performSelectorOnMainThread:withObject:waitUntilDone:modes:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isGreaterThanOrEqualTo_, - object?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_1fdou4m( + _$$ref.pointer, + _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_, + aSelector, + _$$ref$1?.pointer ?? ffi.nullptr, + waitUntilDone, + _$$ref$2?.pointer ?? ffi.nullptr, ); } +} - /// isLessThan: - bool isLessThan(objc.ObjCObject? object) { +/// NSURLClient +extension NSURLClient on objc.NSObject { + /// URL:resourceDataDidBecomeAvailable: + @Deprecated('Use NSURLConnection instead') + void URL(objc.NSURL sender, {required objc.NSData resourceDataDidBecomeAvailable}) { + final _$$ref = object$.ref; + final _$$ref$1 = sender.ref; + final _$$ref$2 = resourceDataDidBecomeAvailable.ref; objc.checkOsVersionInternal( - 'NSObject.isLessThan:', + 'NSObject.URL:resourceDataDidBecomeAvailable:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isLessThan_, - object?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_URL_resourceDataDidBecomeAvailable_, + _$$ref$1.pointer, + _$$ref$2.pointer, ); } - /// isLessThanOrEqualTo: - bool isLessThanOrEqualTo(objc.ObjCObject? object) { + /// URL:resourceDidFailLoadingWithReason: + @Deprecated('Use NSURLConnection instead') + void URL$1(objc.NSURL sender, {required objc.NSString resourceDidFailLoadingWithReason}) { + final _$$ref = object$.ref; + final _$$ref$1 = sender.ref; + final _$$ref$2 = resourceDidFailLoadingWithReason.ref; objc.checkOsVersionInternal( - 'NSObject.isLessThanOrEqualTo:', + 'NSObject.URL:resourceDidFailLoadingWithReason:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isLessThanOrEqualTo_, - object?.ref.pointer ?? ffi.nullptr, + _objc_msgSend_pfv6jd( + _$$ref.pointer, + _sel_URL_resourceDidFailLoadingWithReason_, + _$$ref$1.pointer, + _$$ref$2.pointer, ); } - /// isLike: - bool isLike(objc.NSString object) { + /// URLResourceDidCancelLoading: + @Deprecated('Use NSURLConnection instead') + void URLResourceDidCancelLoading(objc.NSURL sender) { + final _$$ref = object$.ref; + final _$$ref$1 = sender.ref; objc.checkOsVersionInternal( - 'NSObject.isLike:', + 'NSObject.URLResourceDidCancelLoading:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isLike_, object.ref.pointer); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_URLResourceDidCancelLoading_, _$$ref$1.pointer); } - /// isNotEqualTo: - bool isNotEqualTo(objc.ObjCObject? object) { + /// URLResourceDidFinishLoading: + @Deprecated('Use NSURLConnection instead') + void URLResourceDidFinishLoading(objc.NSURL sender) { + final _$$ref = object$.ref; + final _$$ref$1 = sender.ref; objc.checkOsVersionInternal( - 'NSObject.isNotEqualTo:', + 'NSObject.URLResourceDidFinishLoading:', iOS: (false, (2, 0, 0)), macOS: (false, (10, 0, 0)), ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_isNotEqualTo_, - object?.ref.pointer ?? ffi.nullptr, - ); + _objc_msgSend_xtuoz7(_$$ref.pointer, _sel_URLResourceDidFinishLoading_, _$$ref$1.pointer); } } -late final _sel_scriptingIsEqualTo_ = objc.registerName("scriptingIsEqualTo:"); -late final _sel_scriptingIsLessThanOrEqualTo_ = objc.registerName("scriptingIsLessThanOrEqualTo:"); -late final _sel_scriptingIsLessThan_ = objc.registerName("scriptingIsLessThan:"); -late final _sel_scriptingIsGreaterThanOrEqualTo_ = objc.registerName( - "scriptingIsGreaterThanOrEqualTo:", -); -late final _sel_scriptingIsGreaterThan_ = objc.registerName("scriptingIsGreaterThan:"); -late final _sel_scriptingBeginsWith_ = objc.registerName("scriptingBeginsWith:"); -late final _sel_scriptingEndsWith_ = objc.registerName("scriptingEndsWith:"); -late final _sel_scriptingContains_ = objc.registerName("scriptingContains:"); - -/// NSScriptingComparisonMethods -extension NSScriptingComparisonMethods on objc.NSObject { - /// scriptingBeginsWith: - bool scriptingBeginsWith(objc.ObjCObject object) { +/// NSUserInformation +extension NSUserInformation on NSFileManager { + /// homeDirectoryForCurrentUser + objc.NSURL get homeDirectoryForCurrentUser { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.scriptingBeginsWith:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingBeginsWith_, - object.ref.pointer, + 'NSFileManager.homeDirectoryForCurrentUser', + iOS: (true, null), + macOS: (false, (10, 12, 0)), ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_homeDirectoryForCurrentUser); + return objc.NSURL.fromPointer($ret, retain: true, release: true); } - /// scriptingContains: - bool scriptingContains(objc.ObjCObject object) { + /// homeDirectoryForUser: + objc.NSURL? homeDirectoryForUser(objc.NSString userName) { + final _$$ref = object$.ref; + final _$$ref$1 = userName.ref; objc.checkOsVersionInternal( - 'NSObject.scriptingContains:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'NSFileManager.homeDirectoryForUser:', + iOS: (true, null), + macOS: (false, (10, 12, 0)), ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_scriptingContains_, object.ref.pointer); - } - - /// scriptingEndsWith: - bool scriptingEndsWith(objc.ObjCObject object) { - objc.checkOsVersionInternal( - 'NSObject.scriptingEndsWith:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + final $ret = _objc_msgSend_1sotr3r( + _$$ref.pointer, + _sel_homeDirectoryForUser_, + _$$ref$1.pointer, ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_scriptingEndsWith_, object.ref.pointer); + return $ret.address == 0 ? null : objc.NSURL.fromPointer($ret, retain: true, release: true); } - /// scriptingIsEqualTo: - bool scriptingIsEqualTo(objc.ObjCObject object) { + /// temporaryDirectory + objc.NSURL get temporaryDirectory { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'NSObject.scriptingIsEqualTo:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'NSFileManager.temporaryDirectory', + iOS: (false, (10, 0, 0)), + macOS: (false, (10, 12, 0)), ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_scriptingIsEqualTo_, object.ref.pointer); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_temporaryDirectory); + return objc.NSURL.fromPointer($ret, retain: true, release: true); } +} - /// scriptingIsGreaterThan: - bool scriptingIsGreaterThan(objc.ObjCObject object) { - objc.checkOsVersionInternal( - 'NSObject.scriptingIsGreaterThan:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingIsGreaterThan_, - object.ref.pointer, - ); - } +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSData { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock fromPointer( + ffi.Pointer pointer, { + bool retain = false, + bool release = false, + }) => objc.ObjCBlock(pointer, retain: retain, release: release); - /// scriptingIsGreaterThanOrEqualTo: - bool scriptingIsGreaterThanOrEqualTo(objc.ObjCObject object) { - objc.checkOsVersionInternal( - 'NSObject.scriptingIsGreaterThanOrEqualTo:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingIsGreaterThanOrEqualTo_, - object.ref.pointer, - ); - } + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock fromFunctionPointer( + ffi.Pointer arg0)>> ptr, + ) => objc.ObjCBlock( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); - /// scriptingIsLessThan: - bool scriptingIsLessThan(objc.ObjCObject object) { - objc.checkOsVersionInternal( - 'NSObject.scriptingIsLessThan:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingIsLessThan_, - object.ref.pointer, + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock fromFunction( + void Function(objc.NSData) fn, { + bool keepIsolateAlive = true, + }) => objc.ObjCBlock( + objc.newClosureBlock(_closureCallable, (ffi.Pointer arg0) { + return fn(objc.NSData.fromPointer(arg0, retain: true, release: true)); + }, keepIsolateAlive), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This block can be invoked from any thread, but only supports void + /// functions, and is not run synchronously. Async functions (ie returning + /// Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock listener( + void Function(objc.NSData) fn, { + bool keepIsolateAlive = true, + }) { + return objc.ObjCBlock( + objc.newBlockPort(_1w5ousu_wrapListenerBlock_xtuoz7, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_1nuohsl.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0); + }, keepIsolateAlive), + retain: false, + release: true, ); } - /// scriptingIsLessThanOrEqualTo: - bool scriptingIsLessThanOrEqualTo(objc.ObjCObject object) { - objc.checkOsVersionInternal( - 'NSObject.scriptingIsLessThanOrEqualTo:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), - ); - return _objc_msgSend_19nvye5( - object$.ref.pointer, - _sel_scriptingIsLessThanOrEqualTo_, - object.ref.pointer, + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions (ie returning Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock blocking( + void Function(objc.NSData) fn, { + bool keepIsolateAlive = true, + }) { + return objc.ObjCBlock( + objc.newBlockingBlockPort(_1w5ousu_wrapBlockingBlock_xtuoz7, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_1nuohsl.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0); + }, keepIsolateAlive), + retain: false, + release: true, ); } -} - -enum PHAssetResourceType { - PHAssetResourceTypePhoto(1), - PHAssetResourceTypeVideo(2), - PHAssetResourceTypeAudio(3), - PHAssetResourceTypeAlternatePhoto(4), - PHAssetResourceTypeFullSizePhoto(5), - PHAssetResourceTypeFullSizeVideo(6), - PHAssetResourceTypeAdjustmentData(7), - PHAssetResourceTypeAdjustmentBasePhoto(8), - PHAssetResourceTypePairedVideo(9), - PHAssetResourceTypeFullSizePairedVideo(10), - PHAssetResourceTypeAdjustmentBasePairedVideo(11), - PHAssetResourceTypeAdjustmentBaseVideo(12), - PHAssetResourceTypePhotoProxy(19); - final int value; - const PHAssetResourceType(this.value); - - static PHAssetResourceType fromValue(int value) => switch (value) { - 1 => PHAssetResourceTypePhoto, - 2 => PHAssetResourceTypeVideo, - 3 => PHAssetResourceTypeAudio, - 4 => PHAssetResourceTypeAlternatePhoto, - 5 => PHAssetResourceTypeFullSizePhoto, - 6 => PHAssetResourceTypeFullSizeVideo, - 7 => PHAssetResourceTypeAdjustmentData, - 8 => PHAssetResourceTypeAdjustmentBasePhoto, - 9 => PHAssetResourceTypePairedVideo, - 10 => PHAssetResourceTypeFullSizePairedVideo, - 11 => PHAssetResourceTypeAdjustmentBasePairedVideo, - 12 => PHAssetResourceTypeAdjustmentBaseVideo, - 19 => PHAssetResourceTypePhotoProxy, - _ => throw ArgumentError('Unknown value for PHAssetResourceType: $value'), - }; + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => block.ref.target + .cast arg0)>>() + .asFunction)>()(arg0); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer) + >(_closureTrampoline) + .cast(); } -late final _class_PHObject = objc.getClass("PHObject"); - -/// PHObject -extension type PHObject._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject, objc.NSCopying { - /// Constructs a [PHObject] that points to the same underlying object as [other]. - PHObject.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal('PHObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); - assert(isA(object$)); +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSData$CallExtension on objc.ObjCBlock { + void call(objc.NSData arg0) { + final _$$ref = arg0.ref; + return ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ) + > + >() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer) + >()(ref.pointer, _$$ref.pointer); } +} - /// Constructs a [PHObject] that wraps the given raw object pointer. - PHObject.fromPointer( - ffi.Pointer other, { +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > + fromPointer( + ffi.Pointer pointer, { bool retain = false, bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal('PHObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); - assert(isA(object$)); - } - - /// Returns whether [obj] is an instance of [PHObject]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHObject); -} + }) => + objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + >(pointer, retain: retain, release: release); -extension PHObject$Methods on PHObject {} + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > + fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + > + ptr, + ) => + objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + >(objc.newPointerBlock(_fnPtrCallable, ptr.cast()), retain: false, release: true); -late final _class_PHFetchResult = objc.getClass("PHFetchResult"); -late final _sel_firstObject = objc.registerName("firstObject"); + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > + fromFunction( + void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) + fn, { + bool keepIsolateAlive = true, + }) => + objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + >( + objc.newClosureBlock(_closureCallable, ( + ffi.Pointer arg0, + ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, + ) { + return fn( + arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: true, release: true), + arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: true, release: true), + CGImagePropertyOrientation.fromValue(arg2), + arg3.address == 0 + ? null + : objc.NSDictionary.fromPointer(arg3, retain: true, release: true), + ); + }, keepIsolateAlive), + retain: false, + release: true, + ); -/// PHFetchResult -extension type PHFetchResult._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject, objc.NSCopying, objc.NSFastEnumeration { - /// Constructs a [PHFetchResult] that points to the same underlying object as [other]. - PHFetchResult.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHFetchResult', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - assert(isA(object$)); - } - - /// Constructs a [PHFetchResult] that wraps the given raw object pointer. - PHFetchResult.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHFetchResult', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - assert(isA(object$)); - } - - /// Returns whether [obj] is an instance of [PHFetchResult]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHFetchResult); -} - -extension PHFetchResult$Methods on PHFetchResult { - /// firstObject - objc.ObjCObject? get firstObject { - objc.checkOsVersionInternal( - 'PHFetchResult.firstObject', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_firstObject); - return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); - } -} - -enum CGImagePropertyOrientation { - kCGImagePropertyOrientationUp(1), - kCGImagePropertyOrientationUpMirrored(2), - kCGImagePropertyOrientationDown(3), - kCGImagePropertyOrientationDownMirrored(4), - kCGImagePropertyOrientationLeftMirrored(5), - kCGImagePropertyOrientationRight(6), - kCGImagePropertyOrientationRightMirrored(7), - kCGImagePropertyOrientationLeft(8); - - final int value; - const CGImagePropertyOrientation(this.value); - - static CGImagePropertyOrientation fromValue(int value) => switch (value) { - 1 => kCGImagePropertyOrientationUp, - 2 => kCGImagePropertyOrientationUpMirrored, - 3 => kCGImagePropertyOrientationDown, - 4 => kCGImagePropertyOrientationDownMirrored, - 5 => kCGImagePropertyOrientationLeftMirrored, - 6 => kCGImagePropertyOrientationRight, - 7 => kCGImagePropertyOrientationRightMirrored, - 8 => kCGImagePropertyOrientationLeft, - _ => throw ArgumentError('Unknown value for CGImagePropertyOrientation: $value'), - }; -} - -late final _class_PHAsset = objc.getClass("PHAsset"); -late final _sel_modificationDate = objc.registerName("modificationDate"); - -/// WARNING: PHFetchOptions is a stub. To generate bindings for this class, include -/// PHFetchOptions in your config's objc-interfaces list. -/// -/// PHFetchOptions -extension type PHFetchOptions._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject, objc.NSCopying { - /// Constructs a [PHFetchOptions] that points to the same underlying object as [other]. - PHFetchOptions.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHFetchOptions', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - } - - /// Constructs a [PHFetchOptions] that wraps the given raw object pointer. - PHFetchOptions.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHFetchOptions', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - } -} - -late final _sel_fetchAssetsWithLocalIdentifiers_options_ = objc.registerName( - "fetchAssetsWithLocalIdentifiers:options:", -); - -/// WARNING: PHContentEditingInputRequestOptions is a stub. To generate bindings for this class, include -/// PHContentEditingInputRequestOptions in your config's objc-interfaces list. -/// -/// PHContentEditingInputRequestOptions -extension type PHContentEditingInputRequestOptions._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHContentEditingInputRequestOptions] that points to the same underlying object as [other]. - PHContentEditingInputRequestOptions.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHContentEditingInputRequestOptions', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - } - - /// Constructs a [PHContentEditingInputRequestOptions] that wraps the given raw object pointer. - PHContentEditingInputRequestOptions.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHContentEditingInputRequestOptions', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - } -} - -/// WARNING: PHContentEditingInput is a stub. To generate bindings for this class, include -/// PHContentEditingInput in your config's objc-interfaces list. -/// -/// PHContentEditingInput -extension type PHContentEditingInput._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHContentEditingInput] that points to the same underlying object as [other]. - PHContentEditingInput.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHContentEditingInput', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 11, 0)), - ); - } - - /// Constructs a [PHContentEditingInput] that wraps the given raw object pointer. - PHContentEditingInput.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHContentEditingInput', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 11, 0)), - ); - } -} - -/// Construction methods for `objc.ObjCBlock`. -abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { - /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock fromPointer( - ffi.Pointer pointer, { - bool retain = false, - bool release = false, - }) => objc.ObjCBlock( - pointer, - retain: retain, - release: release, - ); - - /// Creates a block from a C function pointer. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc.ObjCBlock - fromFunctionPointer( - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer arg0, - ffi.Pointer arg1, - ) - > - > - ptr, - ) => objc.ObjCBlock( - objc.newPointerBlock(_fnPtrCallable, ptr.cast()), - retain: false, - release: true, - ); - - /// Creates a block from a Dart function. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock fromFunction( - void Function(PHContentEditingInput?, objc.NSDictionary) fn, { - bool keepIsolateAlive = true, - }) => objc.ObjCBlock( - objc.newClosureBlock( - _closureCallable, - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : PHContentEditingInput.fromPointer(arg0, retain: true, release: true), - objc.NSDictionary.fromPointer(arg1, retain: true, release: true), - ), - keepIsolateAlive, - ), - retain: false, - release: true, - ); - - /// Creates a listener block from a Dart function. - /// - /// This is based on FFI's NativeCallable.listener, and has the same - /// capabilities and limitations. This block can be invoked from any thread, - /// but only supports void functions, and is not run synchronously. See - /// NativeCallable.listener for more details. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock listener( - void Function(PHContentEditingInput?, objc.NSDictionary) fn, { - bool keepIsolateAlive = true, - }) { - final raw = objc.newClosureBlock( - _listenerCallable.nativeFunction.cast(), - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : PHContentEditingInput.fromPointer(arg0, retain: false, release: true), - objc.NSDictionary.fromPointer(arg1, retain: false, release: true), - ), - keepIsolateAlive, - ); - final wrapper = _NativeLibrary_wrapListenerBlock_pfv6jd(raw); - objc.objectRelease(raw.cast()); - return objc.ObjCBlock( - wrapper, - retain: false, - release: true, + /// Creates a listener block from a Dart function. + /// + /// This block can be invoked from any thread, but only supports void + /// functions, and is not run synchronously. Async functions (ie returning + /// Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > + listener( + void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) + fn, { + bool keepIsolateAlive = true, + }) { + return objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + >( + objc.newBlockPort(_1w5ousu_wrapListenerBlock_10c3wkj, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_ackv4j.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0, args.arg1, args.arg2, args.arg3); + }, keepIsolateAlive), + retain: false, + release: true, ); } @@ -3292,152 +2785,68 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { /// /// This callback can be invoked from any native thread, and will block the /// caller until the callback is handled by the Dart isolate that created - /// the block. Async functions are not supported. + /// the block. Async functions (ie returning Future) are not supported. /// /// If `keepIsolateAlive` is true, this block will keep this isolate alive /// until it is garbage collected by both Dart and ObjC. If the owner isolate /// has shut down, and the block is invoked by native code, it may block /// indefinitely, or have other undefined behavior. - static objc.ObjCBlock blocking( - void Function(PHContentEditingInput?, objc.NSDictionary) fn, { + static objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > + blocking( + void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) + fn, { bool keepIsolateAlive = true, }) { - final raw = objc.newClosureBlock( - _blockingCallable.nativeFunction.cast(), - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : PHContentEditingInput.fromPointer(arg0, retain: false, release: true), - objc.NSDictionary.fromPointer(arg1, retain: false, release: true), - ), - keepIsolateAlive, - ); - final rawListener = objc.newClosureBlock( - _blockingListenerCallable.nativeFunction.cast(), - (ffi.Pointer arg0, ffi.Pointer arg1) => fn( - arg0.address == 0 - ? null - : PHContentEditingInput.fromPointer(arg0, retain: false, release: true), - objc.NSDictionary.fromPointer(arg1, retain: false, release: true), - ), - keepIsolateAlive, - ); - final wrapper = _NativeLibrary_wrapBlockingBlock_pfv6jd(raw, rawListener, objc.objCContext); - objc.objectRelease(raw.cast()); - objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock( - wrapper, + return objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + >( + objc.newBlockingBlockPort(_1w5ousu_wrapBlockingBlock_10c3wkj, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_ackv4j.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0, args.arg1, args.arg2, args.arg3); + }, keepIsolateAlive), retain: false, release: true, ); } - static void _listenerTrampoline( + static void _fnPtrTrampoline( ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, - ) { - (objc.getBlockClosure(block) - as void Function(ffi.Pointer, ffi.Pointer))( - arg0, - arg1, - ); - objc.objectRelease(block.cast()); - } - - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _listenerCallable = - ffi.NativeCallable< + int arg2, + ffi.Pointer arg3, + ) => block.ref.target + .cast< + ffi.NativeFunction< ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.listener(_listenerTrampoline) - ..keepIsolateAlive = false; - static void _blockingTrampoline( - ffi.Pointer block, - ffi.Pointer waiter, - ffi.Pointer arg0, - ffi.Pointer arg1, - ) { - try { - (objc.getBlockClosure(block) - as void Function(ffi.Pointer, ffi.Pointer))( - arg0, - arg1, - ); - } catch (e) { - } finally { - objc.signalWaiter(waiter); - objc.objectRelease(block.cast()); - } - } - - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _blockingCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.isolateLocal(_blockingTrampoline) - ..keepIsolateAlive = false; - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _blockingListenerCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.listener(_blockingTrampoline) - ..keepIsolateAlive = false; - static void _fnPtrTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ) => block.ref.target - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer arg0, - ffi.Pointer arg1, + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, ) > >() .asFunction< - void Function(ffi.Pointer, ffi.Pointer) - >()(arg0, arg1); + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >()(arg0, arg1, arg2, arg3); static ffi.Pointer _fnPtrCallable = ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, + ffi.Uint32, + ffi.Pointer, ) >(_fnPtrTrampoline) .cast(); @@ -3445,1708 +2854,2392 @@ abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { ffi.Pointer block, ffi.Pointer arg0, ffi.Pointer arg1, + int arg2, + ffi.Pointer arg3, ) => (objc.getBlockClosure(block) - as void Function(ffi.Pointer, ffi.Pointer))( - arg0, - arg1, - ); + as void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ))(arg0, arg1, arg2, arg3); static ffi.Pointer _closureCallable = ffi.Pointer.fromFunction< ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, + ffi.Uint32, + ffi.Pointer, ) >(_closureTrampoline) .cast(); } -/// Call operator for `objc.ObjCBlock`. -extension ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary$CallExtension - on objc.ObjCBlock { - void call(PHContentEditingInput? arg0, objc.NSDictionary arg1) => ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary$CallExtension + on + objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > { + void call( + objc.NSData? arg0, + objc.NSString? arg1, + CGImagePropertyOrientation arg2, + objc.NSDictionary? arg3, + ) { + final _$$ref = arg0?.ref; + final _$$ref$1 = arg1?.ref; + final _$$ref$2 = arg3?.ref; + return ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ffi.Uint32 arg2, + ffi.Pointer arg3, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >()(ref.pointer, arg0?.ref.pointer ?? ffi.nullptr, arg1.ref.pointer); -} - -late final _sel_requestContentEditingInputWithOptions_completionHandler_ = objc.registerName( - "requestContentEditingInputWithOptions:completionHandler:", -); -final _objc_msgSend_jkkt9d = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.UnsignedLong Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - int Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); -late final _sel_cancelContentEditingInputRequest_ = objc.registerName( - "cancelContentEditingInputRequest:", -); -final _objc_msgSend_1i9r4xy = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.UnsignedLong, - ) - > - >() - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, int) - >(); - -/// PHContentEditingInput -extension PHContentEditingInput$1 on PHAsset { - /// cancelContentEditingInputRequest: - void cancelContentEditingInputRequest(int requestID) { - objc.checkOsVersionInternal( - 'PHAsset.cancelContentEditingInputRequest:', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - _objc_msgSend_1i9r4xy(object$.ref.pointer, _sel_cancelContentEditingInputRequest_, requestID); - } - - /// requestContentEditingInputWithOptions:completionHandler: - int requestContentEditingInputWithOptions( - PHContentEditingInputRequestOptions? options, { - required objc.ObjCBlock - completionHandler, - }) { - objc.checkOsVersionInternal( - 'PHAsset.requestContentEditingInputWithOptions:completionHandler:', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - return _objc_msgSend_jkkt9d( - object$.ref.pointer, - _sel_requestContentEditingInputWithOptions_completionHandler_, - options?.ref.pointer ?? ffi.nullptr, - completionHandler.ref.pointer, + >()( + ref.pointer, + _$$ref?.pointer ?? ffi.nullptr, + _$$ref$1?.pointer ?? ffi.nullptr, + arg2.value, + _$$ref$2?.pointer ?? ffi.nullptr, ); } } -/// PHAsset -extension type PHAsset._(objc.ObjCObject object$) implements objc.ObjCObject, PHObject { - /// Constructs a [PHAsset] that points to the same underlying object as [other]. - PHAsset.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal('PHAsset', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); - assert(isA(object$)); - } - - /// Constructs a [PHAsset] that wraps the given raw object pointer. - PHAsset.fromPointer( - ffi.Pointer other, { +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_NSError { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock fromPointer( + ffi.Pointer pointer, { bool retain = false, bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal('PHAsset', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); - assert(isA(object$)); - } + }) => objc.ObjCBlock(pointer, retain: retain, release: release); - /// Returns whether [obj] is an instance of [PHAsset]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAsset); + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock fromFunctionPointer( + ffi.Pointer arg0)>> ptr, + ) => objc.ObjCBlock( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); - /// fetchAssetsWithLocalIdentifiers:options: - static PHFetchResult fetchAssetsWithLocalIdentifiers( - objc.NSArray identifiers, { - PHFetchOptions? options, + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock fromFunction( + void Function(objc.NSError?) fn, { + bool keepIsolateAlive = true, + }) => objc.ObjCBlock( + objc.newClosureBlock(_closureCallable, (ffi.Pointer arg0) { + return fn( + arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: true, release: true), + ); + }, keepIsolateAlive), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This block can be invoked from any thread, but only supports void + /// functions, and is not run synchronously. Async functions (ie returning + /// Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock listener( + void Function(objc.NSError?) fn, { + bool keepIsolateAlive = true, }) { - objc.checkOsVersionInternal( - 'PHAsset.fetchAssetsWithLocalIdentifiers:options:', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); - final $ret = _objc_msgSend_15qeuct( - _class_PHAsset, - _sel_fetchAssetsWithLocalIdentifiers_options_, - identifiers.ref.pointer, - options?.ref.pointer ?? ffi.nullptr, + return objc.ObjCBlock( + objc.newBlockPort(_1w5ousu_wrapListenerBlock_xtuoz7, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_117e0ww.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0); + }, keepIsolateAlive), + retain: false, + release: true, ); - return PHFetchResult.fromPointer($ret, retain: true, release: true); } -} -extension PHAsset$Methods on PHAsset { - /// modificationDate - objc.NSDate? get modificationDate { - objc.checkOsVersionInternal( - 'PHAsset.modificationDate', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions (ie returning Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock blocking( + void Function(objc.NSError?) fn, { + bool keepIsolateAlive = true, + }) { + return objc.ObjCBlock( + objc.newBlockingBlockPort(_1w5ousu_wrapBlockingBlock_xtuoz7, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_117e0ww.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0); + }, keepIsolateAlive), + retain: false, + release: true, ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_modificationDate); - return $ret.address == 0 ? null : objc.NSDate.fromPointer($ret, retain: true, release: true); } -} - -late final _class_UTType = objc.getClass("UTType"); -late final _sel_preferredMIMEType = objc.registerName("preferredMIMEType"); -late final _sel_conformsToType_ = objc.registerName("conformsToType:"); -late final _sel_isSupertypeOfType_ = objc.registerName("isSupertypeOfType:"); -late final _sel_isSubtypeOfType_ = objc.registerName("isSubtypeOfType:"); -late final _sel_supertypes = objc.registerName("supertypes"); -/// Conformance -extension Conformance on UTType { - /// conformsToType: - bool conformsToType(UTType type) { - objc.checkOsVersionInternal( - 'UTType.conformsToType:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), - ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_conformsToType_, type.ref.pointer); + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => block.ref.target + .cast arg0)>>() + .asFunction)>()(arg0); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ) => (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function(ffi.Pointer, ffi.Pointer) + >(_closureTrampoline) + .cast(); +} + +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_NSError$CallExtension + on objc.ObjCBlock { + void call(objc.NSError? arg0) { + final _$$ref = arg0?.ref; + return ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ) + > + >() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer) + >()(ref.pointer, _$$ref?.pointer ?? ffi.nullptr); } +} - /// isSubtypeOfType: - bool isSubtypeOfType(UTType type) { - objc.checkOsVersionInternal( - 'UTType.isSubtypeOfType:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), +/// Construction methods for `objc.ObjCBlock`. +abstract final class ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary { + /// Returns a block that wraps the given raw block pointer. + static objc.ObjCBlock fromPointer( + ffi.Pointer pointer, { + bool retain = false, + bool release = false, + }) => objc.ObjCBlock( + pointer, + retain: retain, + release: release, + ); + + /// Creates a block from a C function pointer. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + static objc.ObjCBlock + fromFunctionPointer( + ffi.Pointer< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ) + > + > + ptr, + ) => objc.ObjCBlock( + objc.newPointerBlock(_fnPtrCallable, ptr.cast()), + retain: false, + release: true, + ); + + /// Creates a block from a Dart function. + /// + /// This block must be invoked by native code running on the same thread as + /// the isolate that registered it. Invoking the block on the wrong thread + /// will result in a crash. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock fromFunction( + void Function(PHContentEditingInput?, objc.NSDictionary) fn, { + bool keepIsolateAlive = true, + }) => objc.ObjCBlock( + objc.newClosureBlock(_closureCallable, ( + ffi.Pointer arg0, + ffi.Pointer arg1, + ) { + return fn( + arg0.address == 0 + ? null + : PHContentEditingInput.fromPointer(arg0, retain: true, release: true), + objc.NSDictionary.fromPointer(arg1, retain: true, release: true), + ); + }, keepIsolateAlive), + retain: false, + release: true, + ); + + /// Creates a listener block from a Dart function. + /// + /// This block can be invoked from any thread, but only supports void + /// functions, and is not run synchronously. Async functions (ie returning + /// Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. + static objc.ObjCBlock listener( + void Function(PHContentEditingInput?, objc.NSDictionary) fn, { + bool keepIsolateAlive = true, + }) { + return objc.ObjCBlock( + objc.newBlockPort(_1w5ousu_wrapListenerBlock_pfv6jd, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_rjvg1n.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0, args.arg1); + }, keepIsolateAlive), + retain: false, + release: true, ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isSubtypeOfType_, type.ref.pointer); } - /// isSupertypeOfType: - bool isSupertypeOfType(UTType type) { - objc.checkOsVersionInternal( - 'UTType.isSupertypeOfType:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), + /// Creates a blocking block from a Dart function. + /// + /// This callback can be invoked from any native thread, and will block the + /// caller until the callback is handled by the Dart isolate that created + /// the block. Async functions (ie returning Future) are not supported. + /// + /// If `keepIsolateAlive` is true, this block will keep this isolate alive + /// until it is garbage collected by both Dart and ObjC. If the owner isolate + /// has shut down, and the block is invoked by native code, it may block + /// indefinitely, or have other undefined behavior. + static objc.ObjCBlock blocking( + void Function(PHContentEditingInput?, objc.NSDictionary) fn, { + bool keepIsolateAlive = true, + }) { + return objc.ObjCBlock( + objc.newBlockingBlockPort(_1w5ousu_wrapBlockingBlock_pfv6jd, ( + ffi.Pointer rawArgs, + ) { + final args = _BlockArgs_rjvg1n.fromPointer(rawArgs, retain: false, release: false); + + fn(args.arg0, args.arg1); + }, keepIsolateAlive), + retain: false, + release: true, ); - return _objc_msgSend_19nvye5(object$.ref.pointer, _sel_isSupertypeOfType_, type.ref.pointer); } - /// supertypes - objc.NSSet get supertypes { - objc.checkOsVersionInternal( - 'UTType.supertypes', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), - ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_supertypes); - return objc.NSSet.fromPointer($ret, retain: true, release: true); + static void _fnPtrTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ) => block.ref.target + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer arg0, + ffi.Pointer arg1, + ) + > + >() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer) + >()(arg0, arg1); + static ffi.Pointer _fnPtrCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(_fnPtrTrampoline) + .cast(); + static void _closureTrampoline( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ) => + (objc.getBlockClosure(block) + as void Function(ffi.Pointer, ffi.Pointer))( + arg0, + arg1, + ); + static ffi.Pointer _closureCallable = + ffi.Pointer.fromFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(_closureTrampoline) + .cast(); +} + +/// Call operator for `objc.ObjCBlock`. +extension ObjCBlock_ffiVoid_PHContentEditingInput_NSDictionary$CallExtension + on objc.ObjCBlock { + void call(PHContentEditingInput? arg0, objc.NSDictionary arg1) { + final _$$ref = arg0?.ref; + final _$$ref$1 = arg1.ref; + return ref.pointer.ref.invoke + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer block, + ffi.Pointer arg0, + ffi.Pointer arg1, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >()(ref.pointer, _$$ref?.pointer ?? ffi.nullptr, _$$ref$1.pointer); } } -late final _sel_typesWithTag_tagClass_conformingToType_ = objc.registerName( - "typesWithTag:tagClass:conformingToType:", -); -late final _sel_tags = objc.registerName("tags"); +/// PHAsset +extension type PHAsset._(objc.ObjCObject object$) implements objc.ObjCObject, PHObject { + /// Constructs a [PHAsset] that points to the same underlying object as [other]. + PHAsset.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal('PHAsset', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); + assert(isA(object$)); + } -/// UTTagSpecification -extension UTTagSpecification on UTType { - /// tags - objc.NSDictionary get tags { - objc.checkOsVersionInternal( - 'UTType.tags', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), - ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_tags); - return objc.NSDictionary.fromPointer($ret, retain: true, release: true); + /// Constructs a [PHAsset] that wraps the given raw object pointer. + PHAsset.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal('PHAsset', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); + assert(isA(object$)); } - /// typesWithTag:tagClass:conformingToType: - static objc.NSArray typesWithTag( - objc.NSString tag, { - required objc.NSString tagClass, - UTType? conformingToType, + /// Returns whether [obj] is an instance of [PHAsset]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAsset); + + /// fetchAssetsWithLocalIdentifiers:options: + static PHFetchResult fetchAssetsWithLocalIdentifiers( + objc.NSArray identifiers, { + PHFetchOptions? options, }) { + final _$$ref = identifiers.ref; + final _$$ref$1 = options?.ref; objc.checkOsVersionInternal( - 'UTType.typesWithTag:tagClass:conformingToType:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), + 'PHAsset.fetchAssetsWithLocalIdentifiers:options:', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), ); - final $ret = _objc_msgSend_11spmsz( - _class_UTType, - _sel_typesWithTag_tagClass_conformingToType_, - tag.ref.pointer, - tagClass.ref.pointer, - conformingToType?.ref.pointer ?? ffi.nullptr, + final $ret = _objc_msgSend_15qeuct( + _class_PHAsset, + _sel_fetchAssetsWithLocalIdentifiers_options_, + _$$ref.pointer, + _$$ref$1?.pointer ?? ffi.nullptr, ); - return objc.NSArray.fromPointer($ret, retain: true, release: true); + return PHFetchResult.fromPointer($ret, retain: true, release: true); } } -late final _sel_exportedTypeWithIdentifier_ = objc.registerName("exportedTypeWithIdentifier:"); -late final _sel_exportedTypeWithIdentifier_conformingToType_ = objc.registerName( - "exportedTypeWithIdentifier:conformingToType:", -); -late final _sel_importedTypeWithIdentifier_ = objc.registerName("importedTypeWithIdentifier:"); -late final _sel_importedTypeWithIdentifier_conformingToType_ = objc.registerName( - "importedTypeWithIdentifier:conformingToType:", -); - -/// LocalConstants -extension LocalConstants on UTType { - /// exportedTypeWithIdentifier: - static UTType exportedTypeWithIdentifier(objc.NSString identifier) { +extension PHAsset$Methods on PHAsset { + /// modificationDate + objc.NSDate? get modificationDate { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'UTType.exportedTypeWithIdentifier:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - _class_UTType, - _sel_exportedTypeWithIdentifier_, - identifier.ref.pointer, + 'PHAsset.modificationDate', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), ); - return UTType.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_modificationDate); + return $ret.address == 0 ? null : objc.NSDate.fromPointer($ret, retain: true, release: true); } +} - /// exportedTypeWithIdentifier:conformingToType: - static UTType exportedTypeWithIdentifier$1( - objc.NSString identifier, { - required UTType conformingToType, - }) { +/// PHAssetResource +extension type PHAssetResource._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHAssetResource] that points to the same underlying object as [other]. + PHAssetResource.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( - 'UTType.exportedTypeWithIdentifier:conformingToType:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), + 'PHAssetResource', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); - final $ret = _objc_msgSend_15qeuct( - _class_UTType, - _sel_exportedTypeWithIdentifier_conformingToType_, - identifier.ref.pointer, - conformingToType.ref.pointer, + assert(isA(object$)); + } + + /// Constructs a [PHAssetResource] that wraps the given raw object pointer. + PHAssetResource.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAssetResource', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); - return UTType.fromPointer($ret, retain: true, release: true); + assert(isA(object$)); } - /// importedTypeWithIdentifier: - static UTType importedTypeWithIdentifier(objc.NSString identifier) { + /// Returns whether [obj] is an instance of [PHAssetResource]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAssetResource); + + /// assetResourcesForAsset: + static objc.NSArray assetResourcesForAsset(PHAsset asset) { + final _$$ref = asset.ref; objc.checkOsVersionInternal( - 'UTType.importedTypeWithIdentifier:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), + 'PHAssetResource.assetResourcesForAsset:', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); final $ret = _objc_msgSend_1sotr3r( - _class_UTType, - _sel_importedTypeWithIdentifier_, - identifier.ref.pointer, + _class_PHAssetResource, + _sel_assetResourcesForAsset_, + _$$ref.pointer, + ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); + } +} + +extension PHAssetResource$Methods on PHAssetResource { + /// contentType + UTType get contentType { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'PHAssetResource.contentType', + iOS: (false, (26, 0, 0)), + macOS: (false, (26, 0, 0)), ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_contentType); return UTType.fromPointer($ret, retain: true, release: true); } - /// importedTypeWithIdentifier:conformingToType: - static UTType importedTypeWithIdentifier$1( - objc.NSString identifier, { - required UTType conformingToType, - }) { + /// originalFilename + objc.NSString get originalFilename { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'UTType.importedTypeWithIdentifier:conformingToType:', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), + 'PHAssetResource.originalFilename', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); - final $ret = _objc_msgSend_15qeuct( - _class_UTType, - _sel_importedTypeWithIdentifier_conformingToType_, - identifier.ref.pointer, - conformingToType.ref.pointer, + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_originalFilename); + return objc.NSString.fromPointer($ret, retain: true, release: true); + } + + /// type + PHAssetResourceType get type { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'PHAssetResource.type', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); - return UTType.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_1or4ucj(_$$ref.pointer, _sel_type); + return PHAssetResourceType.fromValue($ret); } } -/// UTType -extension type UTType._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject, objc.NSCopying, objc.NSSecureCoding { - /// Constructs a [UTType] that points to the same underlying object as [other]. - UTType.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal('UTType', iOS: (false, (14, 0, 0)), macOS: (false, (11, 0, 0))); +/// PHAssetResourceManager +extension type PHAssetResourceManager._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHAssetResourceManager] that points to the same underlying object as [other]. + PHAssetResourceManager.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAssetResourceManager', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); assert(isA(object$)); } - /// Constructs a [UTType] that wraps the given raw object pointer. - UTType.fromPointer( + /// Constructs a [PHAssetResourceManager] that wraps the given raw object pointer. + PHAssetResourceManager.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal('UTType', iOS: (false, (14, 0, 0)), macOS: (false, (11, 0, 0))); + objc.checkOsVersionInternal( + 'PHAssetResourceManager', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); assert(isA(object$)); } - /// Returns whether [obj] is an instance of [UTType]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_UTType); -} + /// Returns whether [obj] is an instance of [PHAssetResourceManager]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAssetResourceManager); -extension UTType$Methods on UTType { - /// preferredMIMEType - objc.NSString? get preferredMIMEType { + /// defaultManager + static PHAssetResourceManager defaultManager() { objc.checkOsVersionInternal( - 'UTType.preferredMIMEType', - iOS: (false, (14, 0, 0)), - macOS: (false, (11, 0, 0)), + 'PHAssetResourceManager.defaultManager', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_preferredMIMEType); - return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(_class_PHAssetResourceManager, _sel_defaultManager); + return PHAssetResourceManager.fromPointer($ret, retain: true, release: true); } } -late final _sel_provideImageData_bytesPerRow_origin__size__userInfo_ = objc.registerName( - "provideImageData:bytesPerRow:origin::size::userInfo:", -); -final _objc_msgSend_haq63t = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Size, - ffi.Size, - ffi.Size, - ffi.Size, - ffi.Size, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - int, - int, - int, - int, - ffi.Pointer, - ) - >(); - -/// WARNING: MTLTexture is a stub. To generate bindings for this class, include -/// MTLTexture in your config's objc-protocols list. -/// -/// MTLTexture -extension type MTLTexture._(objc.ObjCProtocol object$) implements objc.ObjCProtocol { - /// Constructs a [MTLTexture] that points to the same underlying object as [other]. - MTLTexture.as(objc.ObjCObject other) : object$ = other; - - /// Constructs a [MTLTexture] that wraps the given raw object pointer. - MTLTexture.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); +extension PHAssetResourceManager$Methods on PHAssetResourceManager { + /// requestDataForAssetResource:options:dataReceivedHandler:completionHandler: + int requestDataForAssetResource( + PHAssetResource resource, { + PHAssetResourceRequestOptions? options, + required objc.ObjCBlock dataReceivedHandler, + required objc.ObjCBlock completionHandler, + }) { + final _$$ref = object$.ref; + final _$$ref$1 = resource.ref; + final _$$ref$2 = options?.ref; + final _$$ref$3 = dataReceivedHandler.ref; + final _$$ref$4 = completionHandler.ref; + objc.checkOsVersionInternal( + 'PHAssetResourceManager.requestDataForAssetResource:options:dataReceivedHandler:completionHandler:', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + return _objc_msgSend_p4k360( + _$$ref.pointer, + _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_, + _$$ref$1.pointer, + _$$ref$2?.pointer ?? ffi.nullptr, + _$$ref$3.pointer, + _$$ref$4.pointer, + ); + } } -/// WARNING: MTLCommandBuffer is a stub. To generate bindings for this class, include -/// MTLCommandBuffer in your config's objc-protocols list. +/// WARNING: PHAssetResourceRequestOptions is a stub. To generate bindings for this class, include +/// PHAssetResourceRequestOptions in your config's objc-interfaces list. /// -/// MTLCommandBuffer -extension type MTLCommandBuffer._(objc.ObjCProtocol object$) implements objc.ObjCProtocol { - /// Constructs a [MTLCommandBuffer] that points to the same underlying object as [other]. - MTLCommandBuffer.as(objc.ObjCObject other) : object$ = other; +/// PHAssetResourceRequestOptions +extension type PHAssetResourceRequestOptions._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHAssetResourceRequestOptions] that points to the same underlying object as [other]. + PHAssetResourceRequestOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHAssetResourceRequestOptions', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + } - /// Constructs a [MTLCommandBuffer] that wraps the given raw object pointer. - MTLCommandBuffer.fromPointer( + /// Constructs a [PHAssetResourceRequestOptions] that wraps the given raw object pointer. + PHAssetResourceRequestOptions.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, - }) : object$ = objc.ObjCProtocol(other, retain: retain, release: release); + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHAssetResourceRequestOptions', + iOS: (false, (9, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + } } -late final _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_ = objc - .registerName("provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:"); -final _objc_msgSend_1jjfka7 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Size, - ffi.Size, - ffi.Size, - ffi.Size, - ffi.Pointer, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - int, - int, - int, - ffi.Pointer, - ) - >(); +enum PHAssetResourceType { + PHAssetResourceTypePhoto(1), + PHAssetResourceTypeVideo(2), + PHAssetResourceTypeAudio(3), + PHAssetResourceTypeAlternatePhoto(4), + PHAssetResourceTypeFullSizePhoto(5), + PHAssetResourceTypeFullSizeVideo(6), + PHAssetResourceTypeAdjustmentData(7), + PHAssetResourceTypeAdjustmentBasePhoto(8), + PHAssetResourceTypePairedVideo(9), + PHAssetResourceTypeFullSizePairedVideo(10), + PHAssetResourceTypeAdjustmentBasePairedVideo(11), + PHAssetResourceTypeAdjustmentBaseVideo(12), + PHAssetResourceTypePhotoProxy(19); -/// CIImageProvider -extension CIImageProvider on objc.NSObject { - /// provideImageData:bytesPerRow:origin::size::userInfo: - void provideImageData( - ffi.Pointer data, { - required int bytesPerRow, - required int origin, - required int unnamed, - required int size, - required int unnamed$1, - objc.ObjCObject? userInfo, - }) { + final int value; + const PHAssetResourceType(this.value); + + static PHAssetResourceType fromValue(int value) => switch (value) { + 1 => PHAssetResourceTypePhoto, + 2 => PHAssetResourceTypeVideo, + 3 => PHAssetResourceTypeAudio, + 4 => PHAssetResourceTypeAlternatePhoto, + 5 => PHAssetResourceTypeFullSizePhoto, + 6 => PHAssetResourceTypeFullSizeVideo, + 7 => PHAssetResourceTypeAdjustmentData, + 8 => PHAssetResourceTypeAdjustmentBasePhoto, + 9 => PHAssetResourceTypePairedVideo, + 10 => PHAssetResourceTypeFullSizePairedVideo, + 11 => PHAssetResourceTypeAdjustmentBasePairedVideo, + 12 => PHAssetResourceTypeAdjustmentBaseVideo, + 19 => PHAssetResourceTypePhotoProxy, + _ => throw ArgumentError('Unknown value for PHAssetResourceType: $value'), + }; +} + +/// WARNING: PHContentEditingInput is a stub. To generate bindings for this class, include +/// PHContentEditingInput in your config's objc-interfaces list. +/// +/// PHContentEditingInput +extension type PHContentEditingInput._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHContentEditingInput] that points to the same underlying object as [other]. + PHContentEditingInput.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( - 'NSObject.provideImageData:bytesPerRow:origin::size::userInfo:', - iOS: (false, (2, 0, 0)), - macOS: (false, (10, 0, 0)), + 'PHContentEditingInput', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 11, 0)), ); - _objc_msgSend_haq63t( - object$.ref.pointer, - _sel_provideImageData_bytesPerRow_origin__size__userInfo_, - data, - bytesPerRow, - origin, - unnamed, - size, - unnamed$1, - userInfo?.ref.pointer ?? ffi.nullptr, + } + + /// Constructs a [PHContentEditingInput] that wraps the given raw object pointer. + PHContentEditingInput.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHContentEditingInput', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 11, 0)), ); } +} - /// provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo: - void provideImageToMTLTexture( - MTLTexture texture, { - required MTLCommandBuffer commandBuffer, - required int originx, - required int originy, - required int width, - required int height, - objc.ObjCObject? userInfo, +/// PHContentEditingInput +extension PHContentEditingInput$1 on PHAsset { + /// cancelContentEditingInputRequest: + void cancelContentEditingInputRequest(int requestID) { + final _$$ref = object$.ref; + objc.checkOsVersionInternal( + 'PHAsset.cancelContentEditingInputRequest:', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + _objc_msgSend_1i9r4xy(_$$ref.pointer, _sel_cancelContentEditingInputRequest_, requestID); + } + + /// requestContentEditingInputWithOptions:completionHandler: + int requestContentEditingInputWithOptions( + PHContentEditingInputRequestOptions? options, { + required objc.ObjCBlock + completionHandler, }) { + final _$$ref = object$.ref; + final _$$ref$1 = options?.ref; + final _$$ref$2 = completionHandler.ref; objc.checkOsVersionInternal( - 'NSObject.provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:', - macOS: (false, (26, 0, 0)), + 'PHAsset.requestContentEditingInputWithOptions:completionHandler:', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 15, 0)), ); - _objc_msgSend_1jjfka7( - object$.ref.pointer, - _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_, - texture.ref.pointer, - commandBuffer.ref.pointer, - originx, - originy, - width, - height, - userInfo?.ref.pointer ?? ffi.nullptr, + return _objc_msgSend_jkkt9d( + _$$ref.pointer, + _sel_requestContentEditingInputWithOptions_completionHandler_, + _$$ref$1?.pointer ?? ffi.nullptr, + _$$ref$2.pointer, ); } } -late final _class_PHImageRequestOptions = objc.getClass("PHImageRequestOptions"); -late final _sel_setNetworkAccessAllowed_ = objc.registerName("setNetworkAccessAllowed:"); -final _objc_msgSend_1s56lr9 = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Bool, - ) - > - >() - .asFunction< - void Function(ffi.Pointer, ffi.Pointer, bool) - >(); -typedef instancetype = ffi.Pointer; -typedef Dartinstancetype = objc.ObjCObject; -late final _sel_new = objc.registerName("new"); +/// WARNING: PHContentEditingInputRequestOptions is a stub. To generate bindings for this class, include +/// PHContentEditingInputRequestOptions in your config's objc-interfaces list. +/// +/// PHContentEditingInputRequestOptions +extension type PHContentEditingInputRequestOptions._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHContentEditingInputRequestOptions] that points to the same underlying object as [other]. + PHContentEditingInputRequestOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHContentEditingInputRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + } -/// PHImageRequestOptions -extension type PHImageRequestOptions._(objc.ObjCObject object$) + /// Constructs a [PHContentEditingInputRequestOptions] that wraps the given raw object pointer. + PHContentEditingInputRequestOptions.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHContentEditingInputRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + } +} + +/// WARNING: PHFetchOptions is a stub. To generate bindings for this class, include +/// PHFetchOptions in your config's objc-interfaces list. +/// +/// PHFetchOptions +extension type PHFetchOptions._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject, objc.NSCopying { - /// Constructs a [PHImageRequestOptions] that points to the same underlying object as [other]. - PHImageRequestOptions.as(objc.ObjCObject other) : object$ = other { + /// Constructs a [PHFetchOptions] that points to the same underlying object as [other]. + PHFetchOptions.as(objc.ObjCObject other) : object$ = other { objc.checkOsVersionInternal( - 'PHImageRequestOptions', + 'PHFetchOptions', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - assert(isA(object$)); } - /// Constructs a [PHImageRequestOptions] that wraps the given raw object pointer. - PHImageRequestOptions.fromPointer( + /// Constructs a [PHFetchOptions] that wraps the given raw object pointer. + PHFetchOptions.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { objc.checkOsVersionInternal( - 'PHImageRequestOptions', + 'PHFetchOptions', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - assert(isA(object$)); } +} - /// Returns whether [obj] is an instance of [PHImageRequestOptions]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHImageRequestOptions); +/// PHFetchResult +extension type PHFetchResult._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying, objc.NSFastEnumeration { + /// Constructs a [PHFetchResult] that points to the same underlying object as [other]. + PHFetchResult.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHFetchResult', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } - /// new - static PHImageRequestOptions new$() { - final $ret = _objc_msgSend_151sglz(_class_PHImageRequestOptions, _sel_new); - return PHImageRequestOptions.fromPointer($ret, retain: false, release: true); + /// Constructs a [PHFetchResult] that wraps the given raw object pointer. + PHFetchResult.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHFetchResult', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); } - /// Returns a new instance of PHImageRequestOptions constructed with the default `new` method. - PHImageRequestOptions() : this.as(new$().object$); + /// Returns whether [obj] is an instance of [PHFetchResult]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHFetchResult); } -extension PHImageRequestOptions$Methods on PHImageRequestOptions { - /// setNetworkAccessAllowed: - set isNetworkAccessAllowed(bool value) { +extension PHFetchResult$Methods on PHFetchResult { + /// firstObject + objc.ObjCObject? get firstObject { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'PHImageRequestOptions.setNetworkAccessAllowed:', + 'PHFetchResult.firstObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); - _objc_msgSend_1s56lr9(object$.ref.pointer, _sel_setNetworkAccessAllowed_, value); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_firstObject); + return $ret.address == 0 ? null : objc.ObjCObject($ret, retain: true, release: true); } } -late final _class_PHImageManager = objc.getClass("PHImageManager"); - -/// Construction methods for `objc.ObjCBlock`. -abstract final class ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary { - /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > - fromPointer( - ffi.Pointer pointer, { +/// PHImageManager +extension type PHImageManager._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { + /// Constructs a [PHImageManager] that points to the same underlying object as [other]. + PHImageManager.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHImageManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } + + /// Constructs a [PHImageManager] that wraps the given raw object pointer. + PHImageManager.fromPointer( + ffi.Pointer other, { bool retain = false, bool release = false, - }) => - objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - >(pointer, retain: retain, release: release); + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHImageManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); + } - /// Creates a block from a C function pointer. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > - fromFunctionPointer( - ffi.Pointer< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Uint32 arg2, - ffi.Pointer arg3, - ) - > - > - ptr, - ) => - objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - >(objc.newPointerBlock(_fnPtrCallable, ptr.cast()), retain: false, release: true); + /// Returns whether [obj] is an instance of [PHImageManager]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHImageManager); - /// Creates a block from a Dart function. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > - fromFunction( - void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) - fn, { - bool keepIsolateAlive = true, - }) => - objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - >( - objc.newClosureBlock( - _closureCallable, - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) => fn( - arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: true, release: true), - arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: true, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: true, release: true), - ), - keepIsolateAlive, - ), - retain: false, - release: true, - ); + /// defaultManager + static PHImageManager defaultManager() { + objc.checkOsVersionInternal( + 'PHImageManager.defaultManager', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + final $ret = _objc_msgSend_151sglz(_class_PHImageManager, _sel_defaultManager); + return PHImageManager.fromPointer($ret, retain: true, release: true); + } +} - /// Creates a listener block from a Dart function. - /// - /// This is based on FFI's NativeCallable.listener, and has the same - /// capabilities and limitations. This block can be invoked from any thread, - /// but only supports void functions, and is not run synchronously. See - /// NativeCallable.listener for more details. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > - listener( - void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) - fn, { - bool keepIsolateAlive = true, +extension PHImageManager$Methods on PHImageManager { + /// requestImageDataAndOrientationForAsset:options:resultHandler: + int requestImageDataAndOrientationForAsset( + PHAsset asset, { + PHImageRequestOptions? options, + required objc.ObjCBlock< + ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) + > + resultHandler, }) { - final raw = objc.newClosureBlock( - _listenerCallable.nativeFunction.cast(), - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) => fn( - arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: false, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), - ), - keepIsolateAlive, + final _$$ref = object$.ref; + final _$$ref$1 = asset.ref; + final _$$ref$2 = options?.ref; + final _$$ref$3 = resultHandler.ref; + objc.checkOsVersionInternal( + 'PHImageManager.requestImageDataAndOrientationForAsset:options:resultHandler:', + iOS: (false, (13, 0, 0)), + macOS: (false, (10, 15, 0)), + ); + return _objc_msgSend_1urj8nv( + _$$ref.pointer, + _sel_requestImageDataAndOrientationForAsset_options_resultHandler_, + _$$ref$1.pointer, + _$$ref$2?.pointer ?? ffi.nullptr, + _$$ref$3.pointer, ); - final wrapper = _NativeLibrary_wrapListenerBlock_10c3wkj(raw); - objc.objectRelease(raw.cast()); - return objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - >(wrapper, retain: false, release: true); } +} - /// Creates a blocking block from a Dart function. - /// - /// This callback can be invoked from any native thread, and will block the - /// caller until the callback is handled by the Dart isolate that created - /// the block. Async functions are not supported. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. If the owner isolate - /// has shut down, and the block is invoked by native code, it may block - /// indefinitely, or have other undefined behavior. - static objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > - blocking( - void Function(objc.NSData?, objc.NSString?, CGImagePropertyOrientation, objc.NSDictionary?) - fn, { - bool keepIsolateAlive = true, - }) { - final raw = objc.newClosureBlock( - _blockingCallable.nativeFunction.cast(), - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) => fn( - arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: false, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), - ), - keepIsolateAlive, - ); - final rawListener = objc.newClosureBlock( - _blockingListenerCallable.nativeFunction.cast(), - ( - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) => fn( - arg0.address == 0 ? null : objc.NSData.fromPointer(arg0, retain: false, release: true), - arg1.address == 0 ? null : objc.NSString.fromPointer(arg1, retain: false, release: true), - CGImagePropertyOrientation.fromValue(arg2), - arg3.address == 0 - ? null - : objc.NSDictionary.fromPointer(arg3, retain: false, release: true), - ), - keepIsolateAlive, +/// PHImageRequestOptions +extension type PHImageRequestOptions._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHImageRequestOptions] that points to the same underlying object as [other]. + PHImageRequestOptions.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal( + 'PHImageRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), ); - final wrapper = _NativeLibrary_wrapBlockingBlock_10c3wkj(raw, rawListener, objc.objCContext); - objc.objectRelease(raw.cast()); - objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - >(wrapper, retain: false, release: true); + assert(isA(object$)); } - static void _listenerTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) { - (objc.getBlockClosure(block) - as void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ))(arg0, arg1, arg2, arg3); - objc.objectRelease(block.cast()); - } - - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - > - _listenerCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - >.listener(_listenerTrampoline) - ..keepIsolateAlive = false; - static void _blockingTrampoline( - ffi.Pointer block, - ffi.Pointer waiter, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) { - try { - (objc.getBlockClosure(block) - as void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ))(arg0, arg1, arg2, arg3); - } catch (e) { - } finally { - objc.signalWaiter(waiter); - objc.objectRelease(block.cast()); - } + /// Constructs a [PHImageRequestOptions] that wraps the given raw object pointer. + PHImageRequestOptions.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + objc.checkOsVersionInternal( + 'PHImageRequestOptions', + iOS: (false, (8, 0, 0)), + macOS: (false, (10, 13, 0)), + ); + assert(isA(object$)); } - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - > - _blockingCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - >.isolateLocal(_blockingTrampoline) - ..keepIsolateAlive = false; - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - > - _blockingListenerCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - >.listener(_blockingTrampoline) - ..keepIsolateAlive = false; - static void _fnPtrTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) => block.ref.target - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Uint32 arg2, - ffi.Pointer arg3, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >()(arg0, arg1, arg2, arg3); - static ffi.Pointer _fnPtrCallable = - ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - >(_fnPtrTrampoline) - .cast(); - static void _closureTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - int arg2, - ffi.Pointer arg3, - ) => - (objc.getBlockClosure(block) - as void Function( - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ))(arg0, arg1, arg2, arg3); - static ffi.Pointer _closureCallable = - ffi.Pointer.fromFunction< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Uint32, - ffi.Pointer, - ) - >(_closureTrampoline) - .cast(); -} + /// Returns whether [obj] is an instance of [PHImageRequestOptions]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHImageRequestOptions); -/// Call operator for `objc.ObjCBlock`. -extension ObjCBlock_ffiVoid_NSData_NSString_CGImagePropertyOrientation_NSDictionary$CallExtension - on - objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > { - void call( - objc.NSData? arg0, - objc.NSString? arg1, - CGImagePropertyOrientation arg2, - objc.NSDictionary? arg3, - ) => - ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer block, - ffi.Pointer arg0, - ffi.Pointer arg1, - ffi.Uint32 arg2, - ffi.Pointer arg3, - ) - > - >() - .asFunction< - void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - int, - ffi.Pointer, - ) - >()( - ref.pointer, - arg0?.ref.pointer ?? ffi.nullptr, - arg1?.ref.pointer ?? ffi.nullptr, - arg2.value, - arg3?.ref.pointer ?? ffi.nullptr, - ); -} + /// new + static PHImageRequestOptions new$() { + final $ret = _objc_msgSend_151sglz(_class_PHImageRequestOptions, _sel_new); + return PHImageRequestOptions.fromPointer($ret, retain: false, release: true); + } -late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = objc.registerName( - "requestImageDataAndOrientationForAsset:options:resultHandler:", -); -final _objc_msgSend_1urj8nv = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Int32 Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - >() - .asFunction< - int Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >(); + /// Returns a new instance of PHImageRequestOptions constructed with the default `new` method. + PHImageRequestOptions() : this.as(new$().object$); +} -/// PHImageManager -extension type PHImageManager._(objc.ObjCObject object$) implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHImageManager] that points to the same underlying object as [other]. - PHImageManager.as(objc.ObjCObject other) : object$ = other { +extension PHImageRequestOptions$Methods on PHImageRequestOptions { + /// setNetworkAccessAllowed: + set isNetworkAccessAllowed(bool value) { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'PHImageManager', + 'PHImageRequestOptions.setNetworkAccessAllowed:', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0)), ); + _objc_msgSend_1s56lr9(_$$ref.pointer, _sel_setNetworkAccessAllowed_, value); + } +} + +/// PHObject +extension type PHObject._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying { + /// Constructs a [PHObject] that points to the same underlying object as [other]. + PHObject.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal('PHObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); assert(isA(object$)); } - /// Constructs a [PHImageManager] that wraps the given raw object pointer. - PHImageManager.fromPointer( + /// Constructs a [PHObject] that wraps the given raw object pointer. + PHObject.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHImageManager', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), - ); + objc.checkOsVersionInternal('PHObject', iOS: (false, (8, 0, 0)), macOS: (false, (10, 13, 0))); assert(isA(object$)); } - /// Returns whether [obj] is an instance of [PHImageManager]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHImageManager); + /// Returns whether [obj] is an instance of [PHObject]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHObject); +} - /// defaultManager - static PHImageManager defaultManager() { +extension PHObject$Methods on PHObject {} + +/// UTTagSpecification +extension UTTagSpecification on UTType { + /// tags + objc.NSDictionary get tags { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'PHImageManager.defaultManager', - iOS: (false, (8, 0, 0)), - macOS: (false, (10, 13, 0)), + 'UTType.tags', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - final $ret = _objc_msgSend_151sglz(_class_PHImageManager, _sel_defaultManager); - return PHImageManager.fromPointer($ret, retain: true, release: true); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_tags); + return objc.NSDictionary.fromPointer($ret, retain: true, release: true); } -} -extension PHImageManager$Methods on PHImageManager { - /// requestImageDataAndOrientationForAsset:options:resultHandler: - int requestImageDataAndOrientationForAsset( - PHAsset asset, { - PHImageRequestOptions? options, - required objc.ObjCBlock< - ffi.Void Function(objc.NSData?, objc.NSString?, ffi.Uint32, objc.NSDictionary?) - > - resultHandler, + /// typesWithTag:tagClass:conformingToType: + static objc.NSArray typesWithTag( + objc.NSString tag, { + required objc.NSString tagClass, + UTType? conformingToType, }) { + final _$$ref = tag.ref; + final _$$ref$1 = tagClass.ref; + final _$$ref$2 = conformingToType?.ref; objc.checkOsVersionInternal( - 'PHImageManager.requestImageDataAndOrientationForAsset:options:resultHandler:', - iOS: (false, (13, 0, 0)), - macOS: (false, (10, 15, 0)), + 'UTType.typesWithTag:tagClass:conformingToType:', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); - return _objc_msgSend_1urj8nv( - object$.ref.pointer, - _sel_requestImageDataAndOrientationForAsset_options_resultHandler_, - asset.ref.pointer, - options?.ref.pointer ?? ffi.nullptr, - resultHandler.ref.pointer, + final $ret = _objc_msgSend_11spmsz( + _class_UTType, + _sel_typesWithTag_tagClass_conformingToType_, + _$$ref.pointer, + _$$ref$1.pointer, + _$$ref$2?.pointer ?? ffi.nullptr, ); + return objc.NSArray.fromPointer($ret, retain: true, release: true); } } -/// WARNING: PHAssetResourceRequestOptions is a stub. To generate bindings for this class, include -/// PHAssetResourceRequestOptions in your config's objc-interfaces list. -/// -/// PHAssetResourceRequestOptions -extension type PHAssetResourceRequestOptions._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject, objc.NSCopying { - /// Constructs a [PHAssetResourceRequestOptions] that points to the same underlying object as [other]. - PHAssetResourceRequestOptions.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHAssetResourceRequestOptions', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); +/// UTType +extension type UTType._(objc.ObjCObject object$) + implements objc.ObjCObject, objc.NSObject, objc.NSCopying, objc.NSSecureCoding { + /// Constructs a [UTType] that points to the same underlying object as [other]. + UTType.as(objc.ObjCObject other) : object$ = other { + objc.checkOsVersionInternal('UTType', iOS: (false, (14, 0, 0)), macOS: (false, (11, 0, 0))); + assert(isA(object$)); } - /// Constructs a [PHAssetResourceRequestOptions] that wraps the given raw object pointer. - PHAssetResourceRequestOptions.fromPointer( + /// Constructs a [UTType] that wraps the given raw object pointer. + UTType.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHAssetResourceRequestOptions', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); + objc.checkOsVersionInternal('UTType', iOS: (false, (14, 0, 0)), macOS: (false, (11, 0, 0))); + assert(isA(object$)); } -} -late final _class_PHAssetResourceManager = objc.getClass("PHAssetResourceManager"); -late final _class_PHAssetResource = objc.getClass("PHAssetResource"); -late final _sel_type = objc.registerName("type"); -final _objc_msgSend_1or4ucj = objc.msgSendPointer - .cast< - ffi.NativeFunction< - ffi.Long Function(ffi.Pointer, ffi.Pointer) - > - >() - .asFunction, ffi.Pointer)>(); -late final _sel_originalFilename = objc.registerName("originalFilename"); -late final _sel_contentType = objc.registerName("contentType"); -late final _sel_assetResourcesForAsset_ = objc.registerName("assetResourcesForAsset:"); + /// Returns whether [obj] is an instance of [UTType]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_UTType); +} -/// PHAssetResource -extension type PHAssetResource._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHAssetResource] that points to the same underlying object as [other]. - PHAssetResource.as(objc.ObjCObject other) : object$ = other { +extension UTType$Methods on UTType { + /// preferredMIMEType + objc.NSString? get preferredMIMEType { + final _$$ref = object$.ref; objc.checkOsVersionInternal( - 'PHAssetResource', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), + 'UTType.preferredMIMEType', + iOS: (false, (14, 0, 0)), + macOS: (false, (11, 0, 0)), ); + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_preferredMIMEType); + return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); + } +} + +extension type _BlockArgs_117e0ww._(objc.ObjCObject object$) implements objc.ObjCObject { + /// Constructs a [_BlockArgs_117e0ww] that points to the same underlying object as [other]. + _BlockArgs_117e0ww.as(objc.ObjCObject other) : object$ = other { assert(isA(object$)); } - /// Constructs a [PHAssetResource] that wraps the given raw object pointer. - PHAssetResource.fromPointer( + /// Constructs a [_BlockArgs_117e0ww] that wraps the given raw object pointer. + _BlockArgs_117e0ww.fromPointer( ffi.Pointer other, { bool retain = false, bool release = false, }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHAssetResource', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); assert(isA(object$)); } - /// Returns whether [obj] is an instance of [PHAssetResource]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAssetResource); + /// Returns whether [obj] is an instance of [_BlockArgs_117e0ww]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class__BlockArgs_117e0ww); +} - /// assetResourcesForAsset: - static objc.NSArray assetResourcesForAsset(PHAsset asset) { - objc.checkOsVersionInternal( - 'PHAssetResource.assetResourcesForAsset:', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - final $ret = _objc_msgSend_1sotr3r( - _class_PHAssetResource, - _sel_assetResourcesForAsset_, - asset.ref.pointer, - ); - return objc.NSArray.fromPointer($ret, retain: true, release: true); +extension _BlockArgs_117e0ww$Methods on _BlockArgs_117e0ww { + objc.NSError? get arg0 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg0); + return $ret.address == 0 ? null : objc.NSError.fromPointer($ret, retain: true, release: true); } } -extension PHAssetResource$Methods on PHAssetResource { - /// contentType - UTType get contentType { - objc.checkOsVersionInternal( - 'PHAssetResource.contentType', - iOS: (false, (26, 0, 0)), - macOS: (false, (26, 0, 0)), - ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_contentType); - return UTType.fromPointer($ret, retain: true, release: true); +extension type _BlockArgs_1nuohsl._(objc.ObjCObject object$) implements objc.ObjCObject { + /// Constructs a [_BlockArgs_1nuohsl] that points to the same underlying object as [other]. + _BlockArgs_1nuohsl.as(objc.ObjCObject other) : object$ = other { + assert(isA(object$)); } - /// originalFilename - objc.NSString get originalFilename { - objc.checkOsVersionInternal( - 'PHAssetResource.originalFilename', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - final $ret = _objc_msgSend_151sglz(object$.ref.pointer, _sel_originalFilename); - return objc.NSString.fromPointer($ret, retain: true, release: true); + /// Constructs a [_BlockArgs_1nuohsl] that wraps the given raw object pointer. + _BlockArgs_1nuohsl.fromPointer( + ffi.Pointer other, { + bool retain = false, + bool release = false, + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + assert(isA(object$)); } - /// type - PHAssetResourceType get type { - objc.checkOsVersionInternal( - 'PHAssetResource.type', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - final $ret = _objc_msgSend_1or4ucj(object$.ref.pointer, _sel_type); - return PHAssetResourceType.fromValue($ret); + /// Returns whether [obj] is an instance of [_BlockArgs_1nuohsl]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class__BlockArgs_1nuohsl); +} + +extension _BlockArgs_1nuohsl$Methods on _BlockArgs_1nuohsl { + objc.NSData get arg0 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg0); + return objc.NSData.fromPointer($ret, retain: true, release: true); } } -/// Construction methods for `objc.ObjCBlock`. -abstract final class ObjCBlock_ffiVoid_NSData { - /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock fromPointer( - ffi.Pointer pointer, { +extension type _BlockArgs_ackv4j._(objc.ObjCObject object$) implements objc.ObjCObject { + /// Constructs a [_BlockArgs_ackv4j] that points to the same underlying object as [other]. + _BlockArgs_ackv4j.as(objc.ObjCObject other) : object$ = other { + assert(isA(object$)); + } + + /// Constructs a [_BlockArgs_ackv4j] that wraps the given raw object pointer. + _BlockArgs_ackv4j.fromPointer( + ffi.Pointer other, { bool retain = false, bool release = false, - }) => objc.ObjCBlock(pointer, retain: retain, release: release); - - /// Creates a block from a C function pointer. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc.ObjCBlock fromFunctionPointer( - ffi.Pointer arg0)>> ptr, - ) => objc.ObjCBlock( - objc.newPointerBlock(_fnPtrCallable, ptr.cast()), - retain: false, - release: true, - ); + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + assert(isA(object$)); + } - /// Creates a block from a Dart function. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock fromFunction( - void Function(objc.NSData) fn, { - bool keepIsolateAlive = true, - }) => objc.ObjCBlock( - objc.newClosureBlock( - _closureCallable, - (ffi.Pointer arg0) => - fn(objc.NSData.fromPointer(arg0, retain: true, release: true)), - keepIsolateAlive, - ), - retain: false, - release: true, - ); + /// Returns whether [obj] is an instance of [_BlockArgs_ackv4j]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class__BlockArgs_ackv4j); +} - /// Creates a listener block from a Dart function. - /// - /// This is based on FFI's NativeCallable.listener, and has the same - /// capabilities and limitations. This block can be invoked from any thread, - /// but only supports void functions, and is not run synchronously. See - /// NativeCallable.listener for more details. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock listener( - void Function(objc.NSData) fn, { - bool keepIsolateAlive = true, - }) { - final raw = objc.newClosureBlock( - _listenerCallable.nativeFunction.cast(), - (ffi.Pointer arg0) => - fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), - keepIsolateAlive, - ); - final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw); - objc.objectRelease(raw.cast()); - return objc.ObjCBlock(wrapper, retain: false, release: true); +extension _BlockArgs_ackv4j$Methods on _BlockArgs_ackv4j { + objc.NSData? get arg0 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg0); + return $ret.address == 0 ? null : objc.NSData.fromPointer($ret, retain: true, release: true); } - /// Creates a blocking block from a Dart function. - /// - /// This callback can be invoked from any native thread, and will block the - /// caller until the callback is handled by the Dart isolate that created - /// the block. Async functions are not supported. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. If the owner isolate - /// has shut down, and the block is invoked by native code, it may block - /// indefinitely, or have other undefined behavior. - static objc.ObjCBlock blocking( - void Function(objc.NSData) fn, { - bool keepIsolateAlive = true, - }) { - final raw = objc.newClosureBlock( - _blockingCallable.nativeFunction.cast(), - (ffi.Pointer arg0) => - fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), - keepIsolateAlive, - ); - final rawListener = objc.newClosureBlock( - _blockingListenerCallable.nativeFunction.cast(), - (ffi.Pointer arg0) => - fn(objc.NSData.fromPointer(arg0, retain: false, release: true)), - keepIsolateAlive, - ); - final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7(raw, rawListener, objc.objCContext); - objc.objectRelease(raw.cast()); - objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock(wrapper, retain: false, release: true); + objc.NSString? get arg1 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg1); + return $ret.address == 0 ? null : objc.NSString.fromPointer($ret, retain: true, release: true); } - static void _listenerTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ) { - (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); - objc.objectRelease(block.cast()); + CGImagePropertyOrientation get arg2 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_dc3bwt(_$$ref.pointer, _sel_arg2); + return CGImagePropertyOrientation.fromValue($ret); } - static ffi.NativeCallable< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - > - _listenerCallable = - ffi.NativeCallable< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - >.listener(_listenerTrampoline) - ..keepIsolateAlive = false; - static void _blockingTrampoline( - ffi.Pointer block, - ffi.Pointer waiter, - ffi.Pointer arg0, - ) { - try { - (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); - } catch (e) { - } finally { - objc.signalWaiter(waiter); - objc.objectRelease(block.cast()); - } + objc.NSDictionary? get arg3 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg3); + return $ret.address == 0 + ? null + : objc.NSDictionary.fromPointer($ret, retain: true, release: true); } - - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _blockingCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.isolateLocal(_blockingTrampoline) - ..keepIsolateAlive = false; - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _blockingListenerCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.listener(_blockingTrampoline) - ..keepIsolateAlive = false; - static void _fnPtrTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ) => block.ref.target - .cast arg0)>>() - .asFunction)>()(arg0); - static ffi.Pointer _fnPtrCallable = - ffi.Pointer.fromFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - >(_fnPtrTrampoline) - .cast(); - static void _closureTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ) => (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); - static ffi.Pointer _closureCallable = - ffi.Pointer.fromFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - >(_closureTrampoline) - .cast(); } -/// Call operator for `objc.ObjCBlock`. -extension ObjCBlock_ffiVoid_NSData$CallExtension on objc.ObjCBlock { - void call(objc.NSData arg0) => ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer block, - ffi.Pointer arg0, - ) - > - >() - .asFunction< - void Function(ffi.Pointer, ffi.Pointer) - >()(ref.pointer, arg0.ref.pointer); -} +extension type _BlockArgs_rjvg1n._(objc.ObjCObject object$) implements objc.ObjCObject { + /// Constructs a [_BlockArgs_rjvg1n] that points to the same underlying object as [other]. + _BlockArgs_rjvg1n.as(objc.ObjCObject other) : object$ = other { + assert(isA(object$)); + } -/// Construction methods for `objc.ObjCBlock`. -abstract final class ObjCBlock_ffiVoid_NSError { - /// Returns a block that wraps the given raw block pointer. - static objc.ObjCBlock fromPointer( - ffi.Pointer pointer, { + /// Constructs a [_BlockArgs_rjvg1n] that wraps the given raw object pointer. + _BlockArgs_rjvg1n.fromPointer( + ffi.Pointer other, { bool retain = false, bool release = false, - }) => objc.ObjCBlock(pointer, retain: retain, release: release); - - /// Creates a block from a C function pointer. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - static objc.ObjCBlock fromFunctionPointer( - ffi.Pointer arg0)>> ptr, - ) => objc.ObjCBlock( - objc.newPointerBlock(_fnPtrCallable, ptr.cast()), - retain: false, - release: true, - ); - - /// Creates a block from a Dart function. - /// - /// This block must be invoked by native code running on the same thread as - /// the isolate that registered it. Invoking the block on the wrong thread - /// will result in a crash. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock fromFunction( - void Function(objc.NSError?) fn, { - bool keepIsolateAlive = true, - }) => objc.ObjCBlock( - objc.newClosureBlock( - _closureCallable, - (ffi.Pointer arg0) => fn( - arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: true, release: true), - ), - keepIsolateAlive, - ), - retain: false, - release: true, - ); - - /// Creates a listener block from a Dart function. - /// - /// This is based on FFI's NativeCallable.listener, and has the same - /// capabilities and limitations. This block can be invoked from any thread, - /// but only supports void functions, and is not run synchronously. See - /// NativeCallable.listener for more details. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. - static objc.ObjCBlock listener( - void Function(objc.NSError?) fn, { - bool keepIsolateAlive = true, - }) { - final raw = objc.newClosureBlock( - _listenerCallable.nativeFunction.cast(), - (ffi.Pointer arg0) => fn( - arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true), - ), - keepIsolateAlive, - ); - final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw); - objc.objectRelease(raw.cast()); - return objc.ObjCBlock(wrapper, retain: false, release: true); + }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { + assert(isA(object$)); } - /// Creates a blocking block from a Dart function. - /// - /// This callback can be invoked from any native thread, and will block the - /// caller until the callback is handled by the Dart isolate that created - /// the block. Async functions are not supported. - /// - /// If `keepIsolateAlive` is true, this block will keep this isolate alive - /// until it is garbage collected by both Dart and ObjC. If the owner isolate - /// has shut down, and the block is invoked by native code, it may block - /// indefinitely, or have other undefined behavior. - static objc.ObjCBlock blocking( - void Function(objc.NSError?) fn, { - bool keepIsolateAlive = true, - }) { - final raw = objc.newClosureBlock( - _blockingCallable.nativeFunction.cast(), - (ffi.Pointer arg0) => fn( - arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true), - ), - keepIsolateAlive, - ); - final rawListener = objc.newClosureBlock( - _blockingListenerCallable.nativeFunction.cast(), - (ffi.Pointer arg0) => fn( - arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true), - ), - keepIsolateAlive, - ); - final wrapper = _NativeLibrary_wrapBlockingBlock_xtuoz7(raw, rawListener, objc.objCContext); - objc.objectRelease(raw.cast()); - objc.objectRelease(rawListener.cast()); - return objc.ObjCBlock(wrapper, retain: false, release: true); - } - - static void _listenerTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ) { - (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); - objc.objectRelease(block.cast()); - } + /// Returns whether [obj] is an instance of [_BlockArgs_rjvg1n]. + static bool isA(objc.ObjCObject? obj) => obj == null + ? false + : _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class__BlockArgs_rjvg1n); +} - static ffi.NativeCallable< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - > - _listenerCallable = - ffi.NativeCallable< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - >.listener(_listenerTrampoline) - ..keepIsolateAlive = false; - static void _blockingTrampoline( - ffi.Pointer block, - ffi.Pointer waiter, - ffi.Pointer arg0, - ) { - try { - (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); - } catch (e) { - } finally { - objc.signalWaiter(waiter); - objc.objectRelease(block.cast()); - } +extension _BlockArgs_rjvg1n$Methods on _BlockArgs_rjvg1n { + PHContentEditingInput? get arg0 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg0); + return $ret.address == 0 + ? null + : PHContentEditingInput.fromPointer($ret, retain: true, release: true); } - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _blockingCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.isolateLocal(_blockingTrampoline) - ..keepIsolateAlive = false; - static ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - > - _blockingListenerCallable = - ffi.NativeCallable< - ffi.Void Function( - ffi.Pointer, - ffi.Pointer, - ffi.Pointer, - ) - >.listener(_blockingTrampoline) - ..keepIsolateAlive = false; - static void _fnPtrTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ) => block.ref.target - .cast arg0)>>() - .asFunction)>()(arg0); - static ffi.Pointer _fnPtrCallable = - ffi.Pointer.fromFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - >(_fnPtrTrampoline) - .cast(); - static void _closureTrampoline( - ffi.Pointer block, - ffi.Pointer arg0, - ) => (objc.getBlockClosure(block) as void Function(ffi.Pointer))(arg0); - static ffi.Pointer _closureCallable = - ffi.Pointer.fromFunction< - ffi.Void Function(ffi.Pointer, ffi.Pointer) - >(_closureTrampoline) - .cast(); + objc.NSDictionary get arg1 { + final _$$ref = object$.ref; + final $ret = _objc_msgSend_151sglz(_$$ref.pointer, _sel_arg1); + return objc.NSDictionary.fromPointer($ret, retain: true, release: true); + } } -/// Call operator for `objc.ObjCBlock`. -extension ObjCBlock_ffiVoid_NSError$CallExtension - on objc.ObjCBlock { - void call(objc.NSError? arg0) => ref.pointer.ref.invoke - .cast< - ffi.NativeFunction< - ffi.Void Function( - ffi.Pointer block, - ffi.Pointer arg0, - ) - > - >() - .asFunction< - void Function(ffi.Pointer, ffi.Pointer) - >()(ref.pointer, arg0?.ref.pointer ?? ffi.nullptr); -} - -late final _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_ = objc - .registerName("requestDataForAssetResource:options:dataReceivedHandler:completionHandler:"); -final _objc_msgSend_p4k360 = objc.msgSendPointer +@ffi.Native>(symbol: 'OBJC_CLASS_\$_NSFileManager') +external ffi.Pointer _class_NSFileManager_raw; +final _class_NSFileManager = objc.getClass( + "NSFileManager", + () => ffi.Native.addressOf>(_class_NSFileManager_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_NSObject') +external ffi.Pointer _class_NSObject_raw; +final _class_NSObject = objc.getClass( + "NSObject", + () => ffi.Native.addressOf>(_class_NSObject_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHAsset') +external ffi.Pointer _class_PHAsset_raw; +final _class_PHAsset = objc.getClass( + "PHAsset", + () => ffi.Native.addressOf>(_class_PHAsset_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHAssetResource') +external ffi.Pointer _class_PHAssetResource_raw; +final _class_PHAssetResource = objc.getClass( + "PHAssetResource", + () => ffi.Native.addressOf>(_class_PHAssetResource_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHAssetResourceManager') +external ffi.Pointer _class_PHAssetResourceManager_raw; +final _class_PHAssetResourceManager = objc.getClass( + "PHAssetResourceManager", + () => ffi.Native.addressOf>( + _class_PHAssetResourceManager_raw, + ).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHFetchResult') +external ffi.Pointer _class_PHFetchResult_raw; +final _class_PHFetchResult = objc.getClass( + "PHFetchResult", + () => ffi.Native.addressOf>(_class_PHFetchResult_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHImageManager') +external ffi.Pointer _class_PHImageManager_raw; +final _class_PHImageManager = objc.getClass( + "PHImageManager", + () => ffi.Native.addressOf>(_class_PHImageManager_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHImageRequestOptions') +external ffi.Pointer _class_PHImageRequestOptions_raw; +final _class_PHImageRequestOptions = objc.getClass( + "PHImageRequestOptions", + () => ffi.Native.addressOf>( + _class_PHImageRequestOptions_raw, + ).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_PHObject') +external ffi.Pointer _class_PHObject_raw; +final _class_PHObject = objc.getClass( + "PHObject", + () => ffi.Native.addressOf>(_class_PHObject_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$_UTType') +external ffi.Pointer _class_UTType_raw; +final _class_UTType = objc.getClass( + "UTType", + () => ffi.Native.addressOf>(_class_UTType_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$__1w5ousu_BlockArgs_xtuoz7') +external ffi.Pointer _class__BlockArgs_117e0ww_raw; +final _class__BlockArgs_117e0ww = objc.getClass( + "_1w5ousu_BlockArgs_xtuoz7", + () => + ffi.Native.addressOf>(_class__BlockArgs_117e0ww_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$__1w5ousu_BlockArgs_xtuoz7') +external ffi.Pointer _class__BlockArgs_1nuohsl_raw; +final _class__BlockArgs_1nuohsl = objc.getClass( + "_1w5ousu_BlockArgs_xtuoz7", + () => + ffi.Native.addressOf>(_class__BlockArgs_1nuohsl_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$__1w5ousu_BlockArgs_10c3wkj') +external ffi.Pointer _class__BlockArgs_ackv4j_raw; +final _class__BlockArgs_ackv4j = objc.getClass( + "_1w5ousu_BlockArgs_10c3wkj", + () => ffi.Native.addressOf>(_class__BlockArgs_ackv4j_raw).cast(), +); +@ffi.Native>(symbol: 'OBJC_CLASS_\$__1w5ousu_BlockArgs_pfv6jd') +external ffi.Pointer _class__BlockArgs_rjvg1n_raw; +final _class__BlockArgs_rjvg1n = objc.getClass( + "_1w5ousu_BlockArgs_pfv6jd", + () => ffi.Native.addressOf>(_class__BlockArgs_rjvg1n_raw).cast(), +); +final _objc_msgSend_10nfbmq = objc.msgSendPointer .cast< ffi.NativeFunction< - ffi.Int32 Function( + ffi.Void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, + ffi.UnsignedLong, ffi.Pointer, - ffi.Pointer, - ffi.Pointer, ) > >() .asFunction< - int Function( + void Function( ffi.Pointer, ffi.Pointer, ffi.Pointer, + int, ffi.Pointer, - ffi.Pointer, - ffi.Pointer, ) >(); - -/// PHAssetResourceManager -extension type PHAssetResourceManager._(objc.ObjCObject object$) - implements objc.ObjCObject, objc.NSObject { - /// Constructs a [PHAssetResourceManager] that points to the same underlying object as [other]. - PHAssetResourceManager.as(objc.ObjCObject other) : object$ = other { - objc.checkOsVersionInternal( - 'PHAssetResourceManager', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - assert(isA(object$)); - } - - /// Constructs a [PHAssetResourceManager] that wraps the given raw object pointer. - PHAssetResourceManager.fromPointer( - ffi.Pointer other, { - bool retain = false, - bool release = false, - }) : object$ = objc.ObjCObject(other, retain: retain, release: release) { - objc.checkOsVersionInternal( - 'PHAssetResourceManager', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - assert(isA(object$)); - } - - /// Returns whether [obj] is an instance of [PHAssetResourceManager]. - static bool isA(objc.ObjCObject obj) => - _objc_msgSend_19nvye5(obj.ref.pointer, _sel_isKindOfClass_, _class_PHAssetResourceManager); - - /// defaultManager - static PHAssetResourceManager defaultManager() { - objc.checkOsVersionInternal( - 'PHAssetResourceManager.defaultManager', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - final $ret = _objc_msgSend_151sglz(_class_PHAssetResourceManager, _sel_defaultManager); - return PHAssetResourceManager.fromPointer($ret, retain: true, release: true); - } -} - -extension PHAssetResourceManager$Methods on PHAssetResourceManager { - /// requestDataForAssetResource:options:dataReceivedHandler:completionHandler: - int requestDataForAssetResource( - PHAssetResource resource, { - PHAssetResourceRequestOptions? options, - required objc.ObjCBlock dataReceivedHandler, - required objc.ObjCBlock completionHandler, - }) { - objc.checkOsVersionInternal( - 'PHAssetResourceManager.requestDataForAssetResource:options:dataReceivedHandler:completionHandler:', - iOS: (false, (9, 0, 0)), - macOS: (false, (10, 15, 0)), - ); - return _objc_msgSend_p4k360( - object$.ref.pointer, - _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_, - resource.ref.pointer, - options?.ref.pointer ?? ffi.nullptr, - dataReceivedHandler.ref.pointer, - completionHandler.ref.pointer, - ); - } -} +final _objc_msgSend_10txwc9 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_11spmsz = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_151sglz = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_15qeuct = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_19nvye5 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1cc1buo = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1diehjo = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1fdou4m = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1gypgok = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1hz7y9r = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Long Function(ffi.Pointer, ffi.Pointer) + > + >() + .asFunction, ffi.Pointer)>(); +final _objc_msgSend_1i9r4xy = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ) + > + >() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer, int) + >(); +final _objc_msgSend_1j9bhml = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>, + ffi.Pointer, + ffi.Pointer>, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer>, + ffi.Pointer, + ffi.Pointer>, + ) + >(); +final _objc_msgSend_1jed5jl = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1jjfka7 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + int, + int, + int, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1lsax7n = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1or4ucj = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Long Function(ffi.Pointer, ffi.Pointer) + > + >() + .asFunction, ffi.Pointer)>(); +final _objc_msgSend_1pl4k3n = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1qv0eq4 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1s56lr9 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ) + > + >() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer, bool) + >(); +final _objc_msgSend_1sotr3r = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1urj8nv = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_1whyima = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ) + >(); +final _objc_msgSend_1ygbbzi = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_3pyzne = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.UnsignedInt Function(ffi.Pointer, ffi.Pointer) + > + >() + .asFunction, ffi.Pointer)>(); +final _objc_msgSend_4sp4xj = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Long, + ) + > + >() + .asFunction< + void Function(ffi.Pointer, ffi.Pointer, int) + >(); +final _objc_msgSend_6ex6p5 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_7ql5kn = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Double, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + double, + ) + >(); +final _objc_msgSend_7w1jp7 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +final _objc_msgSend_91o635 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function(ffi.Pointer, ffi.Pointer) + > + >() + .asFunction, ffi.Pointer)>(); +final _objc_msgSend_akk2cd = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +final _objc_msgSend_dc3bwt = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Uint32 Function(ffi.Pointer, ffi.Pointer) + > + >() + .asFunction, ffi.Pointer)>(); +final _objc_msgSend_haq63t = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Size, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + int, + int, + int, + int, + ffi.Pointer, + ) + >(); +final _objc_msgSend_jkkt9d = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.UnsignedLong Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_ovsamd = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_p4k360 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Int32 Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + int Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_pfv6jd = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_rutu22 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_s92gih = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_t8ajot = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Double, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + double, + ffi.Pointer, + ) + >(); +final _objc_msgSend_tsocn4 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Bool, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + bool, + ) + >(); +final _objc_msgSend_vbc8p4 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ffi.Pointer, + ) + > + >() + .asFunction< + ffi.Pointer Function( + ffi.Pointer, + ffi.Pointer, + int, + ffi.Pointer, + ) + >(); +final _objc_msgSend_xtuoz7 = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + > + >() + .asFunction< + void Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ) + >(); +final _objc_msgSend_z7gxsm = objc.msgSendPointer + .cast< + ffi.NativeFunction< + ffi.Bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + ffi.UnsignedLong, + ) + > + >() + .asFunction< + bool Function( + ffi.Pointer, + ffi.Pointer, + ffi.Pointer, + int, + ) + >(); +late final _sel_URLResourceDidCancelLoading_ = objc.registerName("URLResourceDidCancelLoading:"); +late final _sel_URLResourceDidFinishLoading_ = objc.registerName("URLResourceDidFinishLoading:"); +late final _sel_URL_resourceDataDidBecomeAvailable_ = objc.registerName( + "URL:resourceDataDidBecomeAvailable:", +); +late final _sel_URL_resourceDidFailLoadingWithReason_ = objc.registerName( + "URL:resourceDidFailLoadingWithReason:", +); +late final _sel_accessInstanceVariablesDirectly = objc.registerName( + "accessInstanceVariablesDirectly", +); +late final _sel_addObserver_forKeyPath_options_context_ = objc.registerName( + "addObserver:forKeyPath:options:context:", +); +late final _sel_arg0 = objc.registerName("arg0"); +late final _sel_arg1 = objc.registerName("arg1"); +late final _sel_arg2 = objc.registerName("arg2"); +late final _sel_arg3 = objc.registerName("arg3"); +late final _sel_assetResourcesForAsset_ = objc.registerName("assetResourcesForAsset:"); +late final _sel_attemptRecoveryFromError_optionIndex_ = objc.registerName( + "attemptRecoveryFromError:optionIndex:", +); +late final _sel_attemptRecoveryFromError_optionIndex_delegate_didRecoverSelector_contextInfo_ = objc + .registerName("attemptRecoveryFromError:optionIndex:delegate:didRecoverSelector:contextInfo:"); +late final _sel_attributeKeys = objc.registerName("attributeKeys"); +late final _sel_autoContentAccessingProxy = objc.registerName("autoContentAccessingProxy"); +late final _sel_automaticallyNotifiesObserversForKey_ = objc.registerName( + "automaticallyNotifiesObserversForKey:", +); +late final _sel_awakeAfterUsingCoder_ = objc.registerName("awakeAfterUsingCoder:"); +late final _sel_cancelContentEditingInputRequest_ = objc.registerName( + "cancelContentEditingInputRequest:", +); +late final _sel_cancelPreviousPerformRequestsWithTarget_ = objc.registerName( + "cancelPreviousPerformRequestsWithTarget:", +); +late final _sel_cancelPreviousPerformRequestsWithTarget_selector_object_ = objc.registerName( + "cancelPreviousPerformRequestsWithTarget:selector:object:", +); +late final _sel_classCode = objc.registerName("classCode"); +late final _sel_classDescription = objc.registerName("classDescription"); +late final _sel_classFallbacksForKeyedArchiver = objc.registerName( + "classFallbacksForKeyedArchiver", +); +late final _sel_classForArchiver = objc.registerName("classForArchiver"); +late final _sel_classForCoder = objc.registerName("classForCoder"); +late final _sel_classForKeyedArchiver = objc.registerName("classForKeyedArchiver"); +late final _sel_classForKeyedUnarchiver = objc.registerName("classForKeyedUnarchiver"); +late final _sel_classForPortCoder = objc.registerName("classForPortCoder"); +late final _sel_className = objc.registerName("className"); +late final _sel_coerceValue_forKey_ = objc.registerName("coerceValue:forKey:"); +late final _sel_conformsToType_ = objc.registerName("conformsToType:"); +late final _sel_contentType = objc.registerName("contentType"); +late final _sel_copyScriptingValue_forKey_withProperties_ = objc.registerName( + "copyScriptingValue:forKey:withProperties:", +); +late final _sel_defaultManager = objc.registerName("defaultManager"); +late final _sel_dictionaryWithValuesForKeys_ = objc.registerName("dictionaryWithValuesForKeys:"); +late final _sel_didChangeValueForKey_ = objc.registerName("didChangeValueForKey:"); +late final _sel_didChangeValueForKey_withSetMutation_usingObjects_ = objc.registerName( + "didChangeValueForKey:withSetMutation:usingObjects:", +); +late final _sel_didChange_valuesAtIndexes_forKey_ = objc.registerName( + "didChange:valuesAtIndexes:forKey:", +); +late final _sel_doesContain_ = objc.registerName("doesContain:"); +late final _sel_exportedTypeWithIdentifier_ = objc.registerName("exportedTypeWithIdentifier:"); +late final _sel_exportedTypeWithIdentifier_conformingToType_ = objc.registerName( + "exportedTypeWithIdentifier:conformingToType:", +); +late final _sel_fetchAssetsWithLocalIdentifiers_options_ = objc.registerName( + "fetchAssetsWithLocalIdentifiers:options:", +); +late final _sel_fileManager_shouldProceedAfterError_ = objc.registerName( + "fileManager:shouldProceedAfterError:", +); +late final _sel_fileManager_willProcessPath_ = objc.registerName("fileManager:willProcessPath:"); +late final _sel_firstObject = objc.registerName("firstObject"); +late final _sel_handleQueryWithUnboundKey_ = objc.registerName("handleQueryWithUnboundKey:"); +late final _sel_handleTakeValue_forUnboundKey_ = objc.registerName( + "handleTakeValue:forUnboundKey:", +); +late final _sel_homeDirectoryForCurrentUser = objc.registerName("homeDirectoryForCurrentUser"); +late final _sel_homeDirectoryForUser_ = objc.registerName("homeDirectoryForUser:"); +late final _sel_importedTypeWithIdentifier_ = objc.registerName("importedTypeWithIdentifier:"); +late final _sel_importedTypeWithIdentifier_conformingToType_ = objc.registerName( + "importedTypeWithIdentifier:conformingToType:", +); +late final _sel_indicesOfObjectsByEvaluatingObjectSpecifier_ = objc.registerName( + "indicesOfObjectsByEvaluatingObjectSpecifier:", +); +late final _sel_insertValue_atIndex_inPropertyWithKey_ = objc.registerName( + "insertValue:atIndex:inPropertyWithKey:", +); +late final _sel_insertValue_inPropertyWithKey_ = objc.registerName( + "insertValue:inPropertyWithKey:", +); +late final _sel_inverseForRelationshipKey_ = objc.registerName("inverseForRelationshipKey:"); +late final _sel_isCaseInsensitiveLike_ = objc.registerName("isCaseInsensitiveLike:"); +late final _sel_isEqualTo_ = objc.registerName("isEqualTo:"); +late final _sel_isGreaterThanOrEqualTo_ = objc.registerName("isGreaterThanOrEqualTo:"); +late final _sel_isGreaterThan_ = objc.registerName("isGreaterThan:"); +late final _sel_isKindOfClass_ = objc.registerName("isKindOfClass:"); +late final _sel_isLessThanOrEqualTo_ = objc.registerName("isLessThanOrEqualTo:"); +late final _sel_isLessThan_ = objc.registerName("isLessThan:"); +late final _sel_isLike_ = objc.registerName("isLike:"); +late final _sel_isNotEqualTo_ = objc.registerName("isNotEqualTo:"); +late final _sel_isReadableFileAtPath_ = objc.registerName("isReadableFileAtPath:"); +late final _sel_isSubtypeOfType_ = objc.registerName("isSubtypeOfType:"); +late final _sel_isSupertypeOfType_ = objc.registerName("isSupertypeOfType:"); +late final _sel_keyPathsForValuesAffectingValueForKey_ = objc.registerName( + "keyPathsForValuesAffectingValueForKey:", +); +late final _sel_modificationDate = objc.registerName("modificationDate"); +late final _sel_mutableArrayValueForKeyPath_ = objc.registerName("mutableArrayValueForKeyPath:"); +late final _sel_mutableArrayValueForKey_ = objc.registerName("mutableArrayValueForKey:"); +late final _sel_mutableOrderedSetValueForKeyPath_ = objc.registerName( + "mutableOrderedSetValueForKeyPath:", +); +late final _sel_mutableOrderedSetValueForKey_ = objc.registerName("mutableOrderedSetValueForKey:"); +late final _sel_mutableSetValueForKeyPath_ = objc.registerName("mutableSetValueForKeyPath:"); +late final _sel_mutableSetValueForKey_ = objc.registerName("mutableSetValueForKey:"); +late final _sel_new = objc.registerName("new"); +late final _sel_newScriptingObjectOfClass_forValueForKey_withContentsValue_properties_ = objc + .registerName("newScriptingObjectOfClass:forValueForKey:withContentsValue:properties:"); +late final _sel_objectSpecifier = objc.registerName("objectSpecifier"); +late final _sel_observationInfo = objc.registerName("observationInfo"); +late final _sel_observeValueForKeyPath_ofObject_change_context_ = objc.registerName( + "observeValueForKeyPath:ofObject:change:context:", +); +late final _sel_originalFilename = objc.registerName("originalFilename"); +late final _sel_performSelectorInBackground_withObject_ = objc.registerName( + "performSelectorInBackground:withObject:", +); +late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_ = objc.registerName( + "performSelectorOnMainThread:withObject:waitUntilDone:", +); +late final _sel_performSelectorOnMainThread_withObject_waitUntilDone_modes_ = objc.registerName( + "performSelectorOnMainThread:withObject:waitUntilDone:modes:", +); +late final _sel_performSelector_onThread_withObject_waitUntilDone_ = objc.registerName( + "performSelector:onThread:withObject:waitUntilDone:", +); +late final _sel_performSelector_onThread_withObject_waitUntilDone_modes_ = objc.registerName( + "performSelector:onThread:withObject:waitUntilDone:modes:", +); +late final _sel_performSelector_withObject_afterDelay_ = objc.registerName( + "performSelector:withObject:afterDelay:", +); +late final _sel_performSelector_withObject_afterDelay_inModes_ = objc.registerName( + "performSelector:withObject:afterDelay:inModes:", +); +late final _sel_preferredMIMEType = objc.registerName("preferredMIMEType"); +late final _sel_provideImageData_bytesPerRow_origin__size__userInfo_ = objc.registerName( + "provideImageData:bytesPerRow:origin::size::userInfo:", +); +late final _sel_provideImageToMTLTexture_commandBuffer_originx_originy_width_height_userInfo_ = objc + .registerName("provideImageToMTLTexture:commandBuffer:originx:originy:width:height:userInfo:"); +late final _sel_removeObserver_forKeyPath_ = objc.registerName("removeObserver:forKeyPath:"); +late final _sel_removeObserver_forKeyPath_context_ = objc.registerName( + "removeObserver:forKeyPath:context:", +); +late final _sel_removeValueAtIndex_fromPropertyWithKey_ = objc.registerName( + "removeValueAtIndex:fromPropertyWithKey:", +); +late final _sel_replaceValueAtIndex_inPropertyWithKey_withValue_ = objc.registerName( + "replaceValueAtIndex:inPropertyWithKey:withValue:", +); +late final _sel_replacementObjectForArchiver_ = objc.registerName("replacementObjectForArchiver:"); +late final _sel_replacementObjectForCoder_ = objc.registerName("replacementObjectForCoder:"); +late final _sel_replacementObjectForKeyedArchiver_ = objc.registerName( + "replacementObjectForKeyedArchiver:", +); +late final _sel_replacementObjectForPortCoder_ = objc.registerName( + "replacementObjectForPortCoder:", +); +late final _sel_requestContentEditingInputWithOptions_completionHandler_ = objc.registerName( + "requestContentEditingInputWithOptions:completionHandler:", +); +late final _sel_requestDataForAssetResource_options_dataReceivedHandler_completionHandler_ = objc + .registerName("requestDataForAssetResource:options:dataReceivedHandler:completionHandler:"); +late final _sel_requestImageDataAndOrientationForAsset_options_resultHandler_ = objc.registerName( + "requestImageDataAndOrientationForAsset:options:resultHandler:", +); +late final _sel_scriptingBeginsWith_ = objc.registerName("scriptingBeginsWith:"); +late final _sel_scriptingContains_ = objc.registerName("scriptingContains:"); +late final _sel_scriptingEndsWith_ = objc.registerName("scriptingEndsWith:"); +late final _sel_scriptingIsEqualTo_ = objc.registerName("scriptingIsEqualTo:"); +late final _sel_scriptingIsGreaterThanOrEqualTo_ = objc.registerName( + "scriptingIsGreaterThanOrEqualTo:", +); +late final _sel_scriptingIsGreaterThan_ = objc.registerName("scriptingIsGreaterThan:"); +late final _sel_scriptingIsLessThanOrEqualTo_ = objc.registerName("scriptingIsLessThanOrEqualTo:"); +late final _sel_scriptingIsLessThan_ = objc.registerName("scriptingIsLessThan:"); +late final _sel_scriptingProperties = objc.registerName("scriptingProperties"); +late final _sel_scriptingValueForSpecifier_ = objc.registerName("scriptingValueForSpecifier:"); +late final _sel_setKeys_triggerChangeNotificationsForDependentKey_ = objc.registerName( + "setKeys:triggerChangeNotificationsForDependentKey:", +); +late final _sel_setNetworkAccessAllowed_ = objc.registerName("setNetworkAccessAllowed:"); +late final _sel_setNilValueForKey_ = objc.registerName("setNilValueForKey:"); +late final _sel_setObservationInfo_ = objc.registerName("setObservationInfo:"); +late final _sel_setScriptingProperties_ = objc.registerName("setScriptingProperties:"); +late final _sel_setSharedObservers_ = objc.registerName("setSharedObservers:"); +late final _sel_setValue_forKeyPath_ = objc.registerName("setValue:forKeyPath:"); +late final _sel_setValue_forKey_ = objc.registerName("setValue:forKey:"); +late final _sel_setValue_forUndefinedKey_ = objc.registerName("setValue:forUndefinedKey:"); +late final _sel_setValuesForKeysWithDictionary_ = objc.registerName( + "setValuesForKeysWithDictionary:", +); +late final _sel_setVersion_ = objc.registerName("setVersion:"); +late final _sel_storedValueForKey_ = objc.registerName("storedValueForKey:"); +late final _sel_supertypes = objc.registerName("supertypes"); +late final _sel_tags = objc.registerName("tags"); +late final _sel_takeStoredValue_forKey_ = objc.registerName("takeStoredValue:forKey:"); +late final _sel_takeValue_forKeyPath_ = objc.registerName("takeValue:forKeyPath:"); +late final _sel_takeValue_forKey_ = objc.registerName("takeValue:forKey:"); +late final _sel_takeValuesFromDictionary_ = objc.registerName("takeValuesFromDictionary:"); +late final _sel_temporaryDirectory = objc.registerName("temporaryDirectory"); +late final _sel_toManyRelationshipKeys = objc.registerName("toManyRelationshipKeys"); +late final _sel_toOneRelationshipKeys = objc.registerName("toOneRelationshipKeys"); +late final _sel_type = objc.registerName("type"); +late final _sel_typesWithTag_tagClass_conformingToType_ = objc.registerName( + "typesWithTag:tagClass:conformingToType:", +); +late final _sel_unableToSetNilForKey_ = objc.registerName("unableToSetNilForKey:"); +late final _sel_useStoredAccessor = objc.registerName("useStoredAccessor"); +late final _sel_validateValue_forKeyPath_error_ = objc.registerName( + "validateValue:forKeyPath:error:", +); +late final _sel_validateValue_forKey_error_ = objc.registerName("validateValue:forKey:error:"); +late final _sel_valueAtIndex_inPropertyWithKey_ = objc.registerName( + "valueAtIndex:inPropertyWithKey:", +); +late final _sel_valueForKeyPath_ = objc.registerName("valueForKeyPath:"); +late final _sel_valueForKey_ = objc.registerName("valueForKey:"); +late final _sel_valueForUndefinedKey_ = objc.registerName("valueForUndefinedKey:"); +late final _sel_valueWithName_inPropertyWithKey_ = objc.registerName( + "valueWithName:inPropertyWithKey:", +); +late final _sel_valueWithUniqueID_inPropertyWithKey_ = objc.registerName( + "valueWithUniqueID:inPropertyWithKey:", +); +late final _sel_valuesForKeys_ = objc.registerName("valuesForKeys:"); +late final _sel_version = objc.registerName("version"); +late final _sel_willChangeValueForKey_ = objc.registerName("willChangeValueForKey:"); +late final _sel_willChangeValueForKey_withSetMutation_usingObjects_ = objc.registerName( + "willChangeValueForKey:withSetMutation:usingObjects:", +); +late final _sel_willChange_valuesAtIndexes_forKey_ = objc.registerName( + "willChange:valuesAtIndexes:forKey:", +); +typedef instancetype = ffi.Pointer; +typedef Dartinstancetype = objc.ObjCObject; diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index ece106740b5e..c52f93ae0dd0 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -33,7 +33,7 @@ dependencies: ffi: ^2.2.0 flutter: sdk: flutter - objective_c: ^9.4.1 + objective_c: ^9.5.0 path: ^1.9.1 dev_dependencies: From a05e32871085af43e5874c6e47832c66f7d21c0a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 6 Aug 2026 16:03:23 -0400 Subject: [PATCH 368/398] formatting --- .../cross_file_darwin_objc/ffi_bindings.g.m | 281 +++++++++--------- 1 file changed, 143 insertions(+), 138 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index afdbd287941b..f8b5fc0d5efc 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -1,7 +1,7 @@ -#include #import -#import #import +#import +#include #if !__has_feature(objc_arc) #error "This file must be compiled with ARC enabled" @@ -12,202 +12,207 @@ typedef struct { int64_t version; - void* (*newWaiter)(void); - void (*awaitWaiter)(void*); - void* (*currentIsolate)(void); - void (*enterIsolate)(void*); + void *(*newWaiter)(void); + void (*awaitWaiter)(void *); + void *(*currentIsolate)(void); + void (*enterIsolate)(void *); void (*exitIsolate)(void); int64_t (*getMainPortId)(void); bool (*getCurrentThreadOwnsIsolate)(int64_t); - void (*invokeListenerPortBlock)(int64_t port, void*); - void (*invokeBlockingPortBlock)(int64_t port, void*, void*); + void (*invokeListenerPortBlock)(int64_t port, void *); + void (*invokeBlockingPortBlock)(int64_t port, void *, void *); } DOBJC_Context; id objc_retainBlock(id); -#define BLOCKING_BLOCK_IMPL(ctx, TYPE, SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ - assert(ctx->version >= 1); \ - void* targetIsolate = ctx->currentIsolate(); \ - int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ - __block __weak TYPE weakSelfBlock = nil; \ - TYPE strongSelfBlock = [SIG { \ - void* currentIsolate = ctx->currentIsolate(); \ - bool mayEnterIsolate = \ - currentIsolate == NULL && \ - ctx->getCurrentThreadOwnsIsolate != NULL && \ - ctx->getCurrentThreadOwnsIsolate(targetPort); \ - if (currentIsolate == targetIsolate || mayEnterIsolate) { \ - if (mayEnterIsolate) { \ - ctx->enterIsolate(targetIsolate); \ - } \ - INVOKE_DIRECT; \ - if (mayEnterIsolate) { \ - ctx->exitIsolate(); \ - } \ - } else { \ - void* waiter = ctx->newWaiter(); \ - TYPE selfRetain = [weakSelfBlock copy]; \ - INVOKE_LISTENER; \ - ctx->awaitWaiter(waiter); \ - (void)selfRetain; \ - } \ - } copy]; \ - weakSelfBlock = strongSelfBlock; \ +#define BLOCKING_BLOCK_IMPL(ctx, TYPE, SIG, INVOKE_DIRECT, INVOKE_LISTENER) \ + assert(ctx->version >= 1); \ + void *targetIsolate = ctx->currentIsolate(); \ + int64_t targetPort = ctx->getMainPortId == NULL ? 0 : ctx->getMainPortId(); \ + __block __weak TYPE weakSelfBlock = nil; \ + TYPE strongSelfBlock = [SIG { \ + void *currentIsolate = ctx->currentIsolate(); \ + bool mayEnterIsolate = currentIsolate == NULL && ctx->getCurrentThreadOwnsIsolate != NULL && \ + ctx->getCurrentThreadOwnsIsolate(targetPort); \ + if (currentIsolate == targetIsolate || mayEnterIsolate) { \ + if (mayEnterIsolate) { \ + ctx->enterIsolate(targetIsolate); \ + } \ + INVOKE_DIRECT; \ + if (mayEnterIsolate) { \ + ctx->exitIsolate(); \ + } \ + } else { \ + void *waiter = ctx->newWaiter(); \ + TYPE selfRetain = [weakSelfBlock copy]; \ + INVOKE_LISTENER; \ + ctx->awaitWaiter(waiter); \ + (void)selfRetain; \ + } \ + } copy]; \ + weakSelfBlock = strongSelfBlock; \ return strongSelfBlock; - __attribute__((visibility("default"))) @interface _1w5ousu_BlockArgs_xtuoz7 : NSObject -@property (copy) id block; -@property (strong) id arg0; +@property(copy) id block; +@property(strong) id arg0; @end @implementation _1w5ousu_BlockArgs_xtuoz7 @end -typedef void (^_ListenerTrampoline)(id arg0); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _1w5ousu_wrapListenerBlock_xtuoz7( - int64_t port, DOBJC_Context* ctx) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline)(id arg0); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline +_1w5ousu_wrapListenerBlock_xtuoz7(int64_t port, DOBJC_Context *ctx) NS_RETURNS_RETAINED { __block __weak _ListenerTrampoline weakSelfBlock = nil; _ListenerTrampoline strongSelfBlock = [^void(id arg0) { @autoreleasepool { - _1w5ousu_BlockArgs_xtuoz7* args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; + _1w5ousu_BlockArgs_xtuoz7 *args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; args.block = weakSelfBlock; args.arg0 = arg0; - ctx->invokeListenerPortBlock(port, (__bridge_retained void*)args); + ctx->invokeListenerPortBlock(port, (__bridge_retained void *)args); } } copy]; weakSelfBlock = strongSelfBlock; return strongSelfBlock; } -typedef void (^_BlockingTrampoline)(void * waiter, id arg0); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline _1w5ousu_wrapBlockingBlock_xtuoz7(int64_t port, DOBJC_Context* ctx, - void (*directInvoke)(void*)) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, _ListenerTrampoline, ^void(id arg0), { - @autoreleasepool { - _1w5ousu_BlockArgs_xtuoz7* args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - directInvoke((__bridge_retained void*)args); - } - }, { - @autoreleasepool { - _1w5ousu_BlockArgs_xtuoz7* args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - ctx->invokeBlockingPortBlock(port, (__bridge_retained void*)args, waiter); - } - }); +typedef void (^_BlockingTrampoline)(void *waiter, id arg0); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline +_1w5ousu_wrapBlockingBlock_xtuoz7(int64_t port, DOBJC_Context *ctx, + void (*directInvoke)(void *)) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL( + ctx, _ListenerTrampoline, ^void(id arg0), + { + @autoreleasepool { + _1w5ousu_BlockArgs_xtuoz7 *args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + directInvoke((__bridge_retained void *)args); + } + }, + { + @autoreleasepool { + _1w5ousu_BlockArgs_xtuoz7 *args = [[_1w5ousu_BlockArgs_xtuoz7 alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + ctx->invokeBlockingPortBlock(port, (__bridge_retained void *)args, waiter); + } + }); } __attribute__((visibility("default"))) @interface _1w5ousu_BlockArgs_10c3wkj : NSObject -@property (copy) id block; -@property (strong) id arg0; -@property (strong) id arg1; +@property(copy) id block; +@property(strong) id arg0; +@property(strong) id arg1; @property CGImagePropertyOrientation arg2; -@property (strong) id arg3; +@property(strong) id arg3; @end @implementation _1w5ousu_BlockArgs_10c3wkj @end -typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _1w5ousu_wrapListenerBlock_10c3wkj( - int64_t port, DOBJC_Context* ctx) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline_1)(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_1 +_1w5ousu_wrapListenerBlock_10c3wkj(int64_t port, DOBJC_Context *ctx) NS_RETURNS_RETAINED { __block __weak _ListenerTrampoline_1 weakSelfBlock = nil; - _ListenerTrampoline_1 strongSelfBlock = [^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { - @autoreleasepool { - _1w5ousu_BlockArgs_10c3wkj* args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - args.arg1 = arg1; - args.arg2 = arg2; - args.arg3 = arg3; - ctx->invokeListenerPortBlock(port, (__bridge_retained void*)args); - } - } copy]; + _ListenerTrampoline_1 strongSelfBlock = + [^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3) { + @autoreleasepool { + _1w5ousu_BlockArgs_10c3wkj *args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + args.arg2 = arg2; + args.arg3 = arg3; + ctx->invokeListenerPortBlock(port, (__bridge_retained void *)args); + } + } copy]; weakSelfBlock = strongSelfBlock; return strongSelfBlock; } -typedef void (^_BlockingTrampoline_1)(void * waiter, id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_1 _1w5ousu_wrapBlockingBlock_10c3wkj(int64_t port, DOBJC_Context* ctx, - void (*directInvoke)(void*)) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, _ListenerTrampoline_1, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), { - @autoreleasepool { - _1w5ousu_BlockArgs_10c3wkj* args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - args.arg1 = arg1; - args.arg2 = arg2; - args.arg3 = arg3; - directInvoke((__bridge_retained void*)args); - } - }, { - @autoreleasepool { - _1w5ousu_BlockArgs_10c3wkj* args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - args.arg1 = arg1; - args.arg2 = arg2; - args.arg3 = arg3; - ctx->invokeBlockingPortBlock(port, (__bridge_retained void*)args, waiter); - } - }); +typedef void (^_BlockingTrampoline_1)(void *waiter, id arg0, id arg1, + CGImagePropertyOrientation arg2, id arg3); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_1 +_1w5ousu_wrapBlockingBlock_10c3wkj(int64_t port, DOBJC_Context *ctx, + void (*directInvoke)(void *)) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL( + ctx, _ListenerTrampoline_1, ^void(id arg0, id arg1, CGImagePropertyOrientation arg2, id arg3), + { + @autoreleasepool { + _1w5ousu_BlockArgs_10c3wkj *args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + args.arg2 = arg2; + args.arg3 = arg3; + directInvoke((__bridge_retained void *)args); + } + }, + { + @autoreleasepool { + _1w5ousu_BlockArgs_10c3wkj *args = [[_1w5ousu_BlockArgs_10c3wkj alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + args.arg2 = arg2; + args.arg3 = arg3; + ctx->invokeBlockingPortBlock(port, (__bridge_retained void *)args, waiter); + } + }); } __attribute__((visibility("default"))) @interface _1w5ousu_BlockArgs_pfv6jd : NSObject -@property (copy) id block; -@property (strong) id arg0; -@property (strong) id arg1; +@property(copy) id block; +@property(strong) id arg0; +@property(strong) id arg1; @end @implementation _1w5ousu_BlockArgs_pfv6jd @end -typedef void (^_ListenerTrampoline_2)(id arg0, id arg1); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _1w5ousu_wrapListenerBlock_pfv6jd( - int64_t port, DOBJC_Context* ctx) NS_RETURNS_RETAINED { +typedef void (^_ListenerTrampoline_2)(id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_2 +_1w5ousu_wrapListenerBlock_pfv6jd(int64_t port, DOBJC_Context *ctx) NS_RETURNS_RETAINED { __block __weak _ListenerTrampoline_2 weakSelfBlock = nil; _ListenerTrampoline_2 strongSelfBlock = [^void(id arg0, id arg1) { @autoreleasepool { - _1w5ousu_BlockArgs_pfv6jd* args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; + _1w5ousu_BlockArgs_pfv6jd *args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; args.block = weakSelfBlock; args.arg0 = arg0; args.arg1 = arg1; - ctx->invokeListenerPortBlock(port, (__bridge_retained void*)args); + ctx->invokeListenerPortBlock(port, (__bridge_retained void *)args); } } copy]; weakSelfBlock = strongSelfBlock; return strongSelfBlock; } -typedef void (^_BlockingTrampoline_2)(void * waiter, id arg0, id arg1); -__attribute__((visibility("default"))) __attribute__((used)) -_ListenerTrampoline_2 _1w5ousu_wrapBlockingBlock_pfv6jd(int64_t port, DOBJC_Context* ctx, - void (*directInvoke)(void*)) NS_RETURNS_RETAINED { - BLOCKING_BLOCK_IMPL(ctx, _ListenerTrampoline_2, ^void(id arg0, id arg1), { - @autoreleasepool { - _1w5ousu_BlockArgs_pfv6jd* args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - args.arg1 = arg1; - directInvoke((__bridge_retained void*)args); - } - }, { - @autoreleasepool { - _1w5ousu_BlockArgs_pfv6jd* args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; - args.block = weakSelfBlock; - args.arg0 = arg0; - args.arg1 = arg1; - ctx->invokeBlockingPortBlock(port, (__bridge_retained void*)args, waiter); - } - }); +typedef void (^_BlockingTrampoline_2)(void *waiter, id arg0, id arg1); +__attribute__((visibility("default"))) __attribute__((used)) _ListenerTrampoline_2 +_1w5ousu_wrapBlockingBlock_pfv6jd(int64_t port, DOBJC_Context *ctx, + void (*directInvoke)(void *)) NS_RETURNS_RETAINED { + BLOCKING_BLOCK_IMPL( + ctx, _ListenerTrampoline_2, ^void(id arg0, id arg1), + { + @autoreleasepool { + _1w5ousu_BlockArgs_pfv6jd *args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + directInvoke((__bridge_retained void *)args); + } + }, + { + @autoreleasepool { + _1w5ousu_BlockArgs_pfv6jd *args = [[_1w5ousu_BlockArgs_pfv6jd alloc] init]; + args.block = weakSelfBlock; + args.arg0 = arg0; + args.arg1 = arg1; + ctx->invokeBlockingPortBlock(port, (__bridge_retained void *)args, waiter); + } + }); } #undef BLOCKING_BLOCK_IMPL From 0694a6c10d4b5a0432993281e25e9705759c310d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 6 Aug 2026 16:10:40 -0400 Subject: [PATCH 369/398] add darwin contributing --- .../cross_file_darwin/CONTRIBUTING.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 packages/cross_file/cross_file_darwin/CONTRIBUTING.md diff --git a/packages/cross_file/cross_file_darwin/CONTRIBUTING.md b/packages/cross_file/cross_file_darwin/CONTRIBUTING.md new file mode 100644 index 000000000000..6c1de4d0592d --- /dev/null +++ b/packages/cross_file/cross_file_darwin/CONTRIBUTING.md @@ -0,0 +1,18 @@ +# Contributing + +## `ffigen` + +This package uses [ffigen](https://pub.dev/packages/ffigen) to call Foundation +methods, rather than using the standard Flutter plugin structure. To add new +functionality to the FFI interface, update `tool/ffigen.dart`, then run: + +```bash +dart run tool/ffigen.dart +``` + +### Configuration philosophy + +This package intentionally uses very strict filtering rules to include only the +necessary methods andg functions. This is partially to keep the package small, +but mostly to avoid unnecessarily generating anything that requires additional +native code helpers. \ No newline at end of file From 74e629ecd108e3d9ab078fbbe958fd99e81f94f9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 6 Aug 2026 16:13:42 -0400 Subject: [PATCH 370/398] remove g --- packages/cross_file/cross_file_darwin/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cross_file/cross_file_darwin/CONTRIBUTING.md b/packages/cross_file/cross_file_darwin/CONTRIBUTING.md index 6c1de4d0592d..fff506e3fcb4 100644 --- a/packages/cross_file/cross_file_darwin/CONTRIBUTING.md +++ b/packages/cross_file/cross_file_darwin/CONTRIBUTING.md @@ -13,6 +13,6 @@ dart run tool/ffigen.dart ### Configuration philosophy This package intentionally uses very strict filtering rules to include only the -necessary methods andg functions. This is partially to keep the package small, +necessary methods and functions. This is partially to keep the package small, but mostly to avoid unnecessarily generating anything that requires additional native code helpers. \ No newline at end of file From 456ff27a1c226a962a3cc7d29d9815f5c2b6444c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:44:40 -0400 Subject: [PATCH 371/398] add dispose method --- .../src/scoped_storage_cross_directory.dart | 3 +++ .../lib/src/scoped_storage_cross_file.dart | 3 +++ .../scoped_storage_cross_directory_test.dart | 11 ++++++++++ .../test/scoped_storage_cross_file_test.dart | 11 ++++++++++ .../cross_file/test/test_stubs.dart | 22 +++++++++++++++++-- ...ndroid_scoped_storage_cross_directory.dart | 5 +++++ .../android_scoped_storage_cross_file.dart | 5 +++++ ...darwin_scoped_storage_cross_directory.dart | 3 +++ .../src/darwin_scoped_storage_cross_file.dart | 8 +++++++ .../lib/src/cross_file_platform.dart | 6 +++++ ...atform_scoped_storage_cross_directory.dart | 3 +++ .../platform_scoped_storage_cross_file.dart | 3 +++ .../src/web_scoped_storage_cross_file.dart | 5 +++++ 13 files changed, 86 insertions(+), 2 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart index 214bba509443..65851cb56d6a 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart @@ -82,4 +82,7 @@ base class ScopedStorageXDirectory extends XDirectory { /// Whether the files in this directory represented by this reference can be /// viewed. Future canRead() => platform.canRead(); + + /// Release the reference this represents. + Future dispose() => platform.dispose(); } diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart index a873c126d79c..e590e48fd481 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart @@ -79,4 +79,7 @@ base class ScopedStorageXFile extends XFile { /// Whether the resource represented by this reference can be read. Future canRead() => platform.canRead(); + + /// Release the reference this represents. + Future dispose() => platform.dispose(); } diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 8b9bab0903c1..052bcec032e8 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -63,5 +63,16 @@ void main() { expect(await file.canRead(), canRead); }); + + test('dispose', () async { + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onDispose: expectAsync0(() async {})), + ); + + final file = ScopedStorageXFile(uri: 'uri'); + + await file.dispose(); + }); }); } diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart index 085caf778ac7..ff297869406b 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_file_test.dart @@ -113,5 +113,16 @@ void main() { expect(await file.canRead(), canRead); }); + + test('dispose', () async { + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformScopedStorageXFile: (PlatformScopedStorageXFileCreationParams params) => + TestScopedStorageXFile(params, onDispose: expectAsync0(() async {})), + ); + + final file = ScopedStorageXFile(uri: 'uri'); + + await file.dispose(); + }); }); } diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 9528dd1f24e1..5d8b1404e461 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -139,6 +139,7 @@ final class TestScopedStorageXFile extends PlatformScopedStorageXFile { this.onOpenRead, this.onReadAsBytes, this.onReadAsString, + this.onDispose, }) : super.implementation(); Future Function()? onCanRead; @@ -149,6 +150,7 @@ final class TestScopedStorageXFile extends PlatformScopedStorageXFile { Stream Function()? onOpenRead; Future Function()? onReadAsBytes; Future Function({required Encoding encoding})? onReadAsString; + Future Function()? onDispose; @override Future canRead() async { @@ -191,15 +193,26 @@ final class TestScopedStorageXFile extends PlatformScopedStorageXFile { Future readAsString({Encoding encoding = utf8}) async { return await onReadAsString?.call(encoding: encoding) ?? ''; } + + @override + Future dispose() async { + return await onDispose?.call(); + } } final class TestScopedStorageXDirectory extends PlatformScopedStorageXDirectory { - TestScopedStorageXDirectory(super.params, {this.onExists, this.onList, this.onCanRead}) - : super.implementation(); + TestScopedStorageXDirectory( + super.params, { + this.onExists, + this.onList, + this.onCanRead, + this.onDispose, + }) : super.implementation(); Future Function()? onExists; Stream Function(ListParams params)? onList; Future Function()? onCanRead; + Future Function()? onDispose; @override Future exists() async { @@ -217,6 +230,11 @@ final class TestScopedStorageXDirectory extends PlatformScopedStorageXDirectory yield* onList!.call(params); } } + + @override + Future dispose() async { + return await onDispose?.call(); + } } final class TestXEntity extends PlatformXEntity { diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index 9303e9e76cd9..63076235b3d4 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -35,4 +35,9 @@ base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirector } } } + + @override + Future dispose() async { + // Reference to the resource does not need to be released. + } } diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 0159b943f634..586594484f1f 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -111,6 +111,11 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { @override Future name() => _documentFile.getName(); + + @override + Future dispose() async { + // Reference to the resource does not need to be released. + } } /// Error thrown when the native [android.InputStream] is not accessible. diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index 6146741f039c..e94bbb10b805 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -119,6 +119,9 @@ base class SecurityScopedDarwinScopedStorageXDirectory extends DarwinScopedStora url.stopAccessingSecurityScopedResource(); } } + + @override + Future dispose() => stopAccessingSecurityScopedResource(); } /// Provides platform-specific features for diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index ddaea3119450..b4274c54e61a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -154,6 +154,9 @@ base class SecurityScopedDarwinScopedStorageXFile extends DarwinScopedStorageXFi url.stopAccessingSecurityScopedResource(); } } + + @override + Future dispose() => stopAccessingSecurityScopedResource(); } /// Implementation of [DarwinScopedStorageXFile] as a representation of a @@ -338,6 +341,11 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile final Uint8List byteView = uint8Pointer.asTypedList(data.length); return Uint8List.fromList(byteView); } + + @override + Future dispose() async { + // Reference to the asset does not need to be released. + } } /// Provides platform-specific features for diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 78a9093fbfba..7802bbf71722 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -125,6 +125,9 @@ final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { Future readAsString({Encoding encoding = utf8}) { throw UnsupportedError('This instance does not represent any resource.'); } + + @override + Future dispose() async => null; } /// Implementation of [PlatformScopedStorageXDirectory} that represents a @@ -142,4 +145,7 @@ final class _DefaultScopedStorageXDirectory extends PlatformScopedStorageXDirect Stream list(ListParams params) { throw UnsupportedError('This instance does not represent any directory.'); } + + @override + Future dispose() async => null; } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index d7c45f21a4cb..d4734a2c5acf 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -98,4 +98,7 @@ abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { /// Whether the files in this directory represented by this reference can be /// viewed. Future canRead(); + + /// Release the reference this represents. + Future dispose(); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index 29b37f375615..0afd1ac83d6b 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -97,4 +97,7 @@ abstract base class PlatformScopedStorageXFile extends PlatformXFile { /// Whether the resource represented by this reference can be read. Future canRead(); + + /// Release the reference this represents. + Future dispose(); } diff --git a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart index 6556ffeeaf80..e8481b759680 100644 --- a/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_web/lib/src/web_scoped_storage_cross_file.dart @@ -171,6 +171,11 @@ base class WebScopedStorageXFile extends PlatformScopedStorageXFile final Blob blob = await getBlob(); return blob.isA() ? (blob as File).name : null; } + + @override + Future dispose() async { + URL.revokeObjectURL(params.uri); + } } /// Provides platform-specific features for [WebScopedStorageXFile]. From 5b936844f2c1a20398aa297c583bce4c4f350865 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:47:49 -0400 Subject: [PATCH 372/398] add file system impl and add test for stream errors --- .../lib/cross_file_platform_interface.dart | 2 + .../lib/src/cross_file_platform.dart | 44 +++++---- .../platform_file_system_cross_directory.dart | 96 +++++++++++++++++++ .../platform_file_system_cross_file.dart | 96 +++++++++++++++++++ .../lib/src/platform_cross_directory.dart | 22 ++--- .../lib/src/platform_cross_file.dart | 22 ++--- .../test/cross_file_platform_test.dart | 95 +++++++++++++----- 7 files changed, 314 insertions(+), 63 deletions(-) create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart create mode 100644 packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart diff --git a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart index 777fe8044c2d..790f897a7bd9 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/cross_file_platform_interface.dart @@ -3,6 +3,8 @@ // found in the LICENSE file. export 'src/cross_file_platform.dart'; +export 'src/file_system/platform_file_system_cross_directory.dart'; +export 'src/file_system/platform_file_system_cross_file.dart'; export 'src/platform_cross_directory.dart'; export 'src/platform_cross_entity.dart'; export 'src/platform_cross_file.dart'; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index 7802bbf71722..e5f234c9db26 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -5,6 +5,8 @@ import 'dart:convert'; import 'dart:typed_data'; +import 'file_system/platform_file_system_cross_directory.dart'; +import 'file_system/platform_file_system_cross_file.dart'; import 'platform_cross_directory.dart'; import 'platform_cross_entity.dart'; import 'platform_cross_file.dart'; @@ -20,13 +22,17 @@ abstract base class CrossFilePlatform { static CrossFilePlatform? instance; /// Creates a new [PlatformXFile]. - PlatformXFile createPlatformXFile(PlatformXFileCreationParams params) { - return _DefaultXFile(params); + PlatformFileSystemXFile createPlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams params, + ) { + return _DefaultFileSystemXFile(params); } - /// Creates a new [PlatformXDirectory]. - PlatformXDirectory createPlatformXDirectory(PlatformXDirectoryCreationParams params) { - return _DefaultXDirectory(params); + /// Creates a new [PlatformFileSystemXDirectory]. + PlatformFileSystemXDirectory createPlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams params, + ) { + return _DefaultFileSystemXDirectory(params); } /// Creates a new [PlatformScopedStorageXDirectory]. @@ -44,10 +50,10 @@ abstract base class CrossFilePlatform { } } -/// Implementation of [PlatformXFile} that represents a resource that does not -/// exist. -final class _DefaultXFile extends PlatformXFile { - _DefaultXFile(super.params) : super.implementation(); +/// Implementation of [PlatformFileSystemXFile} that represents a resource that +/// does not exist. +final class _DefaultFileSystemXFile extends PlatformFileSystemXFile { + _DefaultFileSystemXFile(super.params) : super.implementation(); @override Future exists() async => false; @@ -62,7 +68,7 @@ final class _DefaultXFile extends PlatformXFile { Future name() async => null; @override - Stream openRead([int? start, int? end]) { + Stream openRead([int? start, int? end]) async* { throw UnsupportedError('This instance does not represent any resource.'); } @@ -77,16 +83,16 @@ final class _DefaultXFile extends PlatformXFile { } } -/// Implementation of [PlatformXDirectory} that represents a directory that does -/// not exist. -final class _DefaultXDirectory extends PlatformXDirectory { - _DefaultXDirectory(super.params) : super.implementation(); +/// Implementation of [PlatformFileSystemXDirectory} that represents a directory +/// that does not exist. +final class _DefaultFileSystemXDirectory extends PlatformFileSystemXDirectory { + _DefaultFileSystemXDirectory(super.params) : super.implementation(); @override Future exists() async => false; @override - Stream list(ListParams params) { + Stream list(ListParams params) async* { throw UnsupportedError('This instance does not represent any directory.'); } } @@ -112,7 +118,7 @@ final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { Future name() async => null; @override - Stream openRead([int? start, int? end]) { + Stream openRead([int? start, int? end]) async* { throw UnsupportedError('This instance does not represent any resource.'); } @@ -127,7 +133,7 @@ final class _DefaultScopedStorageXFile extends PlatformScopedStorageXFile { } @override - Future dispose() async => null; + Future dispose() async {} } /// Implementation of [PlatformScopedStorageXDirectory} that represents a @@ -142,10 +148,10 @@ final class _DefaultScopedStorageXDirectory extends PlatformScopedStorageXDirect Future canRead() async => false; @override - Stream list(ListParams params) { + Stream list(ListParams params) async* { throw UnsupportedError('This instance does not represent any directory.'); } @override - Future dispose() async => null; + Future dispose() async {} } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart new file mode 100644 index 000000000000..0821b08a76bf --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart @@ -0,0 +1,96 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; + +import '../cross_file_platform.dart'; +import '../platform_cross_directory.dart'; + +/// Object specifying creation parameters for creating a [PlatformFileSystemXDirectory]. +/// +/// Platform-specific implementations can add additional fields by extending +/// this class. +/// +/// This example demonstrates how to extend the [PlatformFileSystemXDirectoryCreationParams] to +/// provide additional platform-specific parameters. +/// +/// When extending [PlatformFileSystemXDirectoryCreationParams] additional parameters +/// should always accept `null` or have a default value to prevent breaking +/// changes. +/// +/// ```dart +/// base class AndroidFileSystemXDirectoryCreationParams +/// extends PlatformFileSystemXDirectoryCreationParams { +/// AndroidFileSystemXDirectoryCreationParams({required super.uri, this.platformValue}); +/// +/// factory AndroidFileSystemXDirectoryCreationParams.fromCreationParams( +/// PlatformFileSystemXDirectoryCreationParams params, { +/// Object? platformValue, +/// }) { +/// return AndroidFileSystemXDirectoryCreationParams( +/// uri: params.uri, +/// platformValue: platformValue, +/// ); +/// } +/// +/// final Object? platformValue; +/// } +/// ``` +@immutable +base class PlatformFileSystemXDirectoryCreationParams extends PlatformXDirectoryCreationParams { + /// Constructs a [PlatformFileSystemXDirectoryCreationParams]. + const PlatformFileSystemXDirectoryCreationParams({required super.uri}); +} + +/// Base mixin used to provide platform-specific features for implementations of +/// [PlatformFileSystemXDirectory]. +/// +/// When providing platform specific features, platform implementations are +/// expected to declare a mixin that implements this mixin and return an +/// instance with [PlatformFileSystemXDirectory.extension]. +/// +/// ```dart +/// base class AndroidFileSystemXDirectory extends PlatformFileSystemXDirectory with AndroidFileSystemXDirectoryExtension { +/// // ... +/// @override +/// PlatformFileSystemXDirectoryExtension? get extension => this; +/// +/// Future platformMethod() { +/// // ... +/// } +/// } +/// +/// mixin AndroidFileSystemXDirectoryExtension implements PlatformFileSystemXDirectoryExtension { +/// Future platformMethod(); +/// } +/// ``` +mixin PlatformFileSystemXDirectoryExtension implements PlatformXDirectoryExtension {} + +/// A reference to a directory (or folder) on the file system. +abstract base class PlatformFileSystemXDirectory extends PlatformXDirectory { + /// Creates a new [PlatformFileSystemXDirectory] + factory PlatformFileSystemXDirectory(PlatformFileSystemXDirectoryCreationParams params) { + assert( + CrossFilePlatform.instance != null, + 'A platform implementation for `cross_file` has not been set. Please ' + 'ensure that an implementation of `CrossFilePlatform` has been set to ' + '`CrossFilePlatform.instance` before use. For unit testing, ' + '`CrossFilePlatform.instance` can be set with your own test implementation.', + ); + return CrossFilePlatform.instance!.createPlatformFileSystemXDirectory(params); + } + + /// Used by the platform implementation to create a new + /// [PlatformFileSystemXDirectory]. + /// + /// Should only be used by platform implementations because they can't extend + /// a class that only contains a factory constructor. + PlatformFileSystemXDirectory.implementation( + PlatformFileSystemXDirectoryCreationParams super.params, + ) : super.implementation(); + + @override + PlatformFileSystemXDirectoryCreationParams get params => + super.params as PlatformFileSystemXDirectoryCreationParams; +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart new file mode 100644 index 000000000000..fac3984cb1fa --- /dev/null +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart @@ -0,0 +1,96 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/foundation.dart'; + +import '../cross_file_platform.dart'; +import '../platform_cross_file.dart'; + +/// Object specifying creation parameters for creating a [PlatformFileSystemXFile]. +/// +/// Platform-specific implementations can add additional fields by extending +/// this class. +/// +/// This example demonstrates how to extend the [PlatformFileSystemXFileCreationParams] to +/// provide additional platform-specific parameters. +/// +/// When extending [PlatformFileSystemXFileCreationParams] additional parameters +/// should always accept `null` or have a default value to prevent breaking +/// changes. +/// +/// ```dart +/// base class AndroidFileSystemXFileCreationParams +/// extends PlatformFileSystemXFileCreationParams { +/// AndroidFileSystemXFileCreationParams({required super.uri, this.platformValue}); +/// +/// factory AndroidFileSystemXFileCreationParams.fromCreationParams( +/// PlatformFileSystemXFileCreationParams params, { +/// Object? platformValue, +/// }) { +/// return AndroidFileSystemXFileCreationParams( +/// uri: params.uri, +/// platformValue: platformValue, +/// ); +/// } +/// +/// final Object? platformValue; +/// } +/// ``` +@immutable +base class PlatformFileSystemXFileCreationParams extends PlatformXFileCreationParams { + /// Constructs a [PlatformFileSystemXFileCreationParams]. + const PlatformFileSystemXFileCreationParams({required super.uri}); +} + +/// Base mixin used to provide platform-specific features for implementations of +/// [PlatformFileSystemXFile]. +/// +/// When providing platform specific features, platform implementations are +/// expected to declare a mixin that implements this mixin and return an +/// instance with [PlatformFileSystemXFile.extension]. +/// +/// ```dart +/// base class AndroidFileSystemXFile extends PlatformFileSystemXFile with AndroidFileSystemXFileExtension { +/// // ... +/// @override +/// PlatformFileSystemXFileExtension? get extension => this; +/// +/// Future platformMethod() { +/// // ... +/// } +/// } +/// +/// mixin AndroidFileSystemXFileExtension implements PlatformFileSystemXFileExtension { +/// Future platformMethod(); +/// } +/// ``` +mixin PlatformFileSystemXFileExtension implements PlatformXFileExtension {} + +/// Interface for a reference to a local data resource on the file system. +abstract base class PlatformFileSystemXFile extends PlatformXFile { + /// Creates a new [PlatformFileSystemXFile] + factory PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams params) { + assert( + CrossFilePlatform.instance != null, + 'A platform implementation for `cross_file` has not been set. Please ' + 'ensure that an implementation of `CrossFilePlatform` has been set to ' + '`CrossFilePlatform.instance` before use. For unit testing, ' + '`CrossFilePlatform.instance` can be set with your own test implementation.', + ); + return CrossFilePlatform.instance!.createPlatformFileSystemXFile(params); + } + + /// Used by the platform implementation to create a new + /// [PlatformFileSystemXFile]. + /// + /// Should only be used by platform implementations because they can't extend + /// a class that only contains a factory constructor. + @protected + PlatformFileSystemXFile.implementation(PlatformFileSystemXFileCreationParams super.params) + : super.implementation(); + + @override + PlatformFileSystemXFileCreationParams get params => + super.params as PlatformFileSystemXFileCreationParams; +} diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 191385290870..4434f33ce527 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -71,17 +71,17 @@ mixin PlatformXDirectoryExtension implements PlatformXEntityExtension {} /// Interface for a reference to a directory (or folder) on the file system. abstract base class PlatformXDirectory extends PlatformXEntity { - /// Creates a new [PlatformXDirectory]. - factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { - assert( - CrossFilePlatform.instance != null, - 'A platform implementation for `cross_file` has not been set. Please ' - 'ensure that an implementation of `CrossFilePlatform` has been set to ' - '`CrossFilePlatform.instance` before use. For unit testing, ' - '`CrossFilePlatform.instance` can be set with your own test implementation.', - ); - return CrossFilePlatform.instance!.createPlatformXDirectory(params); - } + // /// Creates a new [PlatformXDirectory]. + // factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { + // assert( + // CrossFilePlatform.instance != null, + // 'A platform implementation for `cross_file` has not been set. Please ' + // 'ensure that an implementation of `CrossFilePlatform` has been set to ' + // '`CrossFilePlatform.instance` before use. For unit testing, ' + // '`CrossFilePlatform.instance` can be set with your own test implementation.', + // ); + // return CrossFilePlatform.instance!.createPlatformXDirectory(params); + // } /// Used by the platform implementation to create a new [PlatformXDirectory]. /// diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 02de71daf8e7..956822fc1c18 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -72,17 +72,17 @@ mixin PlatformXFileExtension implements PlatformXEntityExtension {} /// Interface for a reference to a local data resource. abstract base class PlatformXFile extends PlatformXEntity { - /// Creates a new [PlatformXFile]. - factory PlatformXFile(PlatformXFileCreationParams params) { - assert( - CrossFilePlatform.instance != null, - 'A platform implementation for `cross_file` has not been set. Please ' - 'ensure that an implementation of `CrossFilePlatform` has been set to ' - '`CrossFilePlatform.instance` before use. For unit testing, ' - '`CrossFilePlatform.instance` can be set with your own test implementation.', - ); - return CrossFilePlatform.instance!.createPlatformXFile(params); - } + // /// Creates a new [PlatformXFile]. + // factory PlatformXFile(PlatformXFileCreationParams params) { + // assert( + // CrossFilePlatform.instance != null, + // 'A platform implementation for `cross_file` has not been set. Please ' + // 'ensure that an implementation of `CrossFilePlatform` has been set to ' + // '`CrossFilePlatform.instance` before use. For unit testing, ' + // '`CrossFilePlatform.instance` can be set with your own test implementation.', + // ); + // return CrossFilePlatform.instance!.createPlatformXFile(params); + // } /// Used by the platform implementation to create a new [PlatformXFile]. /// diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 6c6385d7f238..8fd5f8a0c057 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -7,37 +7,62 @@ import 'package:flutter_test/flutter_test.dart'; void main() { group('CrossFilePlatform', () { - test( - 'Default implementation of createPlatformXFile should return an implementation that returns false for exists()', - () async { + group('FileSystem', () { + test('_DefaultFileSystemXFile.exists() returns false', () async { final platform = TestCrossFilePlatform(); expect( await platform - .createPlatformXFile(const PlatformXFileCreationParams(uri: 'test')) + .createPlatformFileSystemXFile( + const PlatformFileSystemXFileCreationParams(uri: 'test'), + ) .exists(), false, ); - }, - ); + }); - test( - 'Default implementation of createPlatformXDirectory should return an implementation that returns false for exists()', - () async { + test('_DefaultFileSystemXFile.openRead should throw error by adding it to stream', () async { + final platform = TestCrossFilePlatform(); + + final PlatformFileSystemXFile file = platform.createPlatformFileSystemXFile( + const PlatformFileSystemXFileCreationParams(uri: 'test'), + ); + + // Ensures the error is caught and added to the stream. + await expectLater(file.openRead().drain, throwsUnsupportedError); + }); + + test('_DefaultFileSystemXDirectory.exists() returns false', () async { final platform = TestCrossFilePlatform(); expect( await platform - .createPlatformXDirectory(const PlatformXDirectoryCreationParams(uri: 'test')) + .createPlatformFileSystemXDirectory( + const PlatformFileSystemXDirectoryCreationParams(uri: 'test'), + ) .exists(), false, ); - }, - ); + }); + + test( + '_DefaultFileSystemXDirectory.list should throw error by adding it to stream', + () async { + final platform = TestCrossFilePlatform(); + + final PlatformFileSystemXDirectory dir = platform + .createPlatformFileSystemXDirectory( + const PlatformFileSystemXDirectoryCreationParams(uri: 'test'), + ); - test( - 'Default implementation of createPlatformScopedStorageXFile should return an implementation that returns false for exists()', - () async { + // Ensures the error is caught and added to the stream. + await expectLater(dir.list(ListParams()).drain, throwsUnsupportedError); + }, + ); + }); + + group('ScopedStorage', () { + test('_DefaultScopedStorageXFile.exists() returns false', () async { final platform = TestCrossFilePlatform(); expect( @@ -48,12 +73,23 @@ void main() { .exists(), false, ); - }, - ); + }); + + test( + '_DefaultScopedStorageXFile.openRead should throw error by adding it to stream', + () async { + final platform = TestCrossFilePlatform(); + + final PlatformScopedStorageXFile file = platform.createPlatformScopedStorageXFile( + const PlatformScopedStorageXFileCreationParams(uri: 'test'), + ); - test( - 'Default implementation of createPlatformScopedStorageXDirectory should return an implementation that returns false for exists()', - () async { + // Ensures the error is caught and added to the stream. + await expectLater(file.openRead().drain, throwsUnsupportedError); + }, + ); + + test('_DefaultScopedStorageXDirectory.exists() returns false', () async { final platform = TestCrossFilePlatform(); expect( @@ -64,8 +100,23 @@ void main() { .exists(), false, ); - }, - ); + }); + + test( + '_DefaultScopedStorageXDirectory.list should throw error by adding it to stream', + () async { + final platform = TestCrossFilePlatform(); + + final PlatformScopedStorageXDirectory dir = platform + .createPlatformScopedStorageXDirectory( + const PlatformScopedStorageXDirectoryCreationParams(uri: 'test'), + ); + + // Ensures the error is caught and added to the stream. + await expectLater(dir.list(ListParams()).drain, throwsUnsupportedError); + }, + ); + }); }); } From 0e6f093d7007497fb1f35dd6e00420e1740cdfe1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 11:58:32 -0400 Subject: [PATCH 373/398] switch to range error and ensure error is sent to stream --- .../cross_file/lib/src/cross_file.dart | 9 +++++---- .../android_scoped_storage_cross_file.dart | 4 ++-- .../src/darwin_scoped_storage_cross_file.dart | 20 +++++++++---------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index d4068b963251..fce9313e45cc 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -93,15 +93,16 @@ base class XFile extends XEntity { /// /// Platforms may throw an exception if there is an error opening or reading /// the resource. - Stream openRead([int? start, int? end]) { + Stream openRead([int? start, int? end]) async* { if (start != null && start < 0) { - throw ArgumentError('`start` must be greater than 0. start: $start'); + throw RangeError('`start` must be greater than 0. start: $start'); } else if (end != null && end <= (start ?? 0)) { - throw ArgumentError( + throw RangeError( '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', ); } - return platform.openRead(start, end); + + yield* platform.openRead(start, end); } /// Reads the entire resource contents as a list of bytes. diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart index 586594484f1f..daab8341716f 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_file.dart @@ -55,9 +55,9 @@ base class AndroidScopedStorageXFile extends PlatformScopedStorageXFile { @override Stream openRead([int? start, int? end]) async* { if (start != null && start < 0) { - throw ArgumentError('`start` must be greater than 0. start: $start'); + throw RangeError('`start` must be greater than 0. start: $start'); } else if (end != null && end <= (start ?? 0)) { - throw ArgumentError( + throw RangeError( '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', ); } diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index b4274c54e61a..6ad17d0cdd17 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -203,26 +203,26 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile @override Stream openRead([int? start, int? end]) { if (start != null && start < 0) { - throw ArgumentError('`start` must be greater than 0. start: $start'); + return Stream.error(RangeError('`start` must be greater than 0. start: $start')); } else if (end != null && end <= (start ?? 0)) { - throw ArgumentError( - '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', + return Stream.error( + RangeError( + '`end` must be greater than 0 and greater than `start`. start: $start, end: $end', + ), ); } - final streamController = StreamController(); - - final filter = ByteRangeFilter(start: 0, end: end); - final PHAssetResource? resource = _tryGetAssetResource(identifier: params.uri); if (resource == null) { - streamController.addError( + return Stream.error( Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), ); - streamController.close(); - return streamController.stream; } + final streamController = StreamController(); + + final filter = ByteRangeFilter(start: 0, end: end); + void dataReceivedHandler(NSData data) { final Uint8List bytes = _extractBytesToUint8List(data); From c6ee25f8aef4542db52e59a472e2f568746cec1a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:12:46 -0400 Subject: [PATCH 374/398] add file system to interface --- .../cross_file/lib/src/cross_directory.dart | 4 ++-- .../platform_file_system_cross_directory.dart | 2 +- .../platform_file_system_cross_file.dart | 3 +-- .../lib/src/platform_cross_directory.dart | 21 +++---------------- .../lib/src/platform_cross_entity.dart | 3 ++- .../lib/src/platform_cross_file.dart | 20 ++---------------- ...atform_scoped_storage_cross_directory.dart | 2 +- .../platform_scoped_storage_cross_file.dart | 3 +-- 8 files changed, 13 insertions(+), 45 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 67024b9c1b41..47367f780a9e 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -10,9 +10,9 @@ import 'cross_file.dart'; import 'scoped_storage_cross_directory.dart'; import 'scoped_storage_cross_file.dart'; -/// A reference to a directory (or folder) on the file system. +/// A reference to a container of local data resources. /// -/// Note: Not all platforms support directories. +/// Note: Not all platforms support accessing directories. /// /// ## Platform-Specific Features /// This class contains an underlying implementation provided by the current diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart index 0821b08a76bf..000f99f1009a 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart @@ -88,7 +88,7 @@ abstract base class PlatformFileSystemXDirectory extends PlatformXDirectory { /// a class that only contains a factory constructor. PlatformFileSystemXDirectory.implementation( PlatformFileSystemXDirectoryCreationParams super.params, - ) : super.implementation(); + ); @override PlatformFileSystemXDirectoryCreationParams get params => diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart index fac3984cb1fa..ed4c2c45cf5c 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart @@ -87,8 +87,7 @@ abstract base class PlatformFileSystemXFile extends PlatformXFile { /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformFileSystemXFile.implementation(PlatformFileSystemXFileCreationParams super.params) - : super.implementation(); + PlatformFileSystemXFile.implementation(PlatformFileSystemXFileCreationParams super.params); @override PlatformFileSystemXFileCreationParams get params => diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 4434f33ce527..64fade77d0b3 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -69,26 +69,11 @@ base class PlatformXDirectoryCreationParams extends PlatformXEntityCreationParam /// ``` mixin PlatformXDirectoryExtension implements PlatformXEntityExtension {} -/// Interface for a reference to a directory (or folder) on the file system. +/// Interface for a reference to a container of local data resources. abstract base class PlatformXDirectory extends PlatformXEntity { - // /// Creates a new [PlatformXDirectory]. - // factory PlatformXDirectory(PlatformXDirectoryCreationParams params) { - // assert( - // CrossFilePlatform.instance != null, - // 'A platform implementation for `cross_file` has not been set. Please ' - // 'ensure that an implementation of `CrossFilePlatform` has been set to ' - // '`CrossFilePlatform.instance` before use. For unit testing, ' - // '`CrossFilePlatform.instance` can be set with your own test implementation.', - // ); - // return CrossFilePlatform.instance!.createPlatformXDirectory(params); - // } - - /// Used by the platform implementation to create a new [PlatformXDirectory]. - /// - /// Should only be used by platform implementations because they can't extend - /// a class that only contains a factory constructor. + /// Constructs a [PlatformXDirectory]. @protected - PlatformXDirectory.implementation(PlatformXDirectoryCreationParams super.params); + PlatformXDirectory(PlatformXDirectoryCreationParams super.params); @override PlatformXDirectoryCreationParams get params => super.params as PlatformXDirectoryCreationParams; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart index e573e010f3a0..707815b4cf43 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_entity.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:flutter/foundation.dart' show immutable; +import 'package:flutter/foundation.dart' show immutable, protected; /// The common superclass for [PlatformXFileCreationParams] and /// [PlatformXDirectoryCreationParams]. @@ -22,6 +22,7 @@ mixin PlatformXEntityExtension {} /// The common superclass for [PlatformXFile] and [PlatformXDirectory]. abstract base class PlatformXEntity { /// Constructs a [PlatformCrossFileEntity]. + @protected PlatformXEntity(this.params); /// The parameters used to initialize the [PlatformXEntity]. diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart index 956822fc1c18..7fe099516fdb 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_file.dart @@ -7,7 +7,6 @@ import 'dart:typed_data'; import 'package:flutter/foundation.dart' show immutable, protected; -import 'cross_file_platform.dart'; import 'platform_cross_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXFile]. @@ -72,24 +71,9 @@ mixin PlatformXFileExtension implements PlatformXEntityExtension {} /// Interface for a reference to a local data resource. abstract base class PlatformXFile extends PlatformXEntity { - // /// Creates a new [PlatformXFile]. - // factory PlatformXFile(PlatformXFileCreationParams params) { - // assert( - // CrossFilePlatform.instance != null, - // 'A platform implementation for `cross_file` has not been set. Please ' - // 'ensure that an implementation of `CrossFilePlatform` has been set to ' - // '`CrossFilePlatform.instance` before use. For unit testing, ' - // '`CrossFilePlatform.instance` can be set with your own test implementation.', - // ); - // return CrossFilePlatform.instance!.createPlatformXFile(params); - // } - - /// Used by the platform implementation to create a new [PlatformXFile]. - /// - /// Should only be used by platform implementations because they can't extend - /// a class that only contains a factory constructor. + /// Constructs a [PlatformXFile]. @protected - PlatformXFile.implementation(PlatformXFileCreationParams super.params); + PlatformXFile(PlatformXFileCreationParams super.params); @override PlatformXFileCreationParams get params => super.params as PlatformXFileCreationParams; diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index d4734a2c5acf..c1784742d21d 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -89,7 +89,7 @@ abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { /// a class that only contains a factory constructor. PlatformScopedStorageXDirectory.implementation( PlatformScopedStorageXDirectoryCreationParams super.params, - ) : super.implementation(); + ); @override PlatformScopedStorageXDirectoryCreationParams get params => diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart index 0afd1ac83d6b..2d3d2056de0e 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_file.dart @@ -88,8 +88,7 @@ abstract base class PlatformScopedStorageXFile extends PlatformXFile { /// Should only be used by platform implementations because they can't extend /// a class that only contains a factory constructor. @protected - PlatformScopedStorageXFile.implementation(PlatformScopedStorageXFileCreationParams super.params) - : super.implementation(); + PlatformScopedStorageXFile.implementation(PlatformScopedStorageXFileCreationParams super.params); @override PlatformScopedStorageXFileCreationParams get params => From f828a3b81d624710c0f2dbf5c90aab5460c0941c Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:35:48 -0400 Subject: [PATCH 375/398] app facing toString uses uri and change filesystem params to use path instead of uri --- .../cross_file/lib/src/cross_directory.dart | 3 ++ .../cross_file/lib/src/cross_file.dart | 3 ++ .../lib/src/io_cross_directory.dart | 2 +- .../cross_file_io/lib/src/io_cross_file.dart | 38 ++++++++++--------- .../platform_file_system_cross_directory.dart | 2 +- .../platform_file_system_cross_file.dart | 2 +- .../test/cross_file_platform_test.dart | 28 ++++++-------- 7 files changed, 40 insertions(+), 38 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index 47367f780a9e..e825ef46ca3b 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -100,4 +100,7 @@ base class XDirectory extends XEntity { return XEntity(entity); }); } + + @override + String toString() => platform.params.uri; } diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index fce9313e45cc..c5ceb6289e89 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -124,4 +124,7 @@ base class XFile extends XEntity { /// If the file is identified by a path, only the base name of the file will /// be included in the name. Future name() => platform.name(); + + @override + String toString() => platform.params.uri; } diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart index bdb97c89e522..c7e3890e9c7d 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart @@ -31,7 +31,7 @@ base class IOXDirectoryCreationParams extends PlatformXDirectoryCreationParams { /// Implementation of [PlatformXDirectory] for dart:io. base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { /// Constructs an [IOXDirectory]. - IOXDirectory(super.params) : super.implementation(); + IOXDirectory(super.params); @override late final IOXDirectoryCreationParams params = super.params is IOXDirectoryCreationParams diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index b0e0cc56174b..b7fa43efc007 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -10,33 +10,35 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'package:flutter/foundation.dart' show immutable; import 'package:path/path.dart' as path; -/// Implementation of [PlatformXFileCreationParams] for dart:io. +/// Implementation of [PlatformFileSystemXFileCreationParams] for dart:io. @immutable -base class IOXFileCreationParams extends PlatformXFileCreationParams { - /// Constructs an [IOXFileCreationParams]. - IOXFileCreationParams({required String uri}) : this.fromFile(File.fromUri(Uri.parse(uri))); +base class IOFileSystemXFileCreationParams extends PlatformFileSystemXFileCreationParams { + /// Constructs an [IOFileSystemXFileCreationParams]. + IOFileSystemXFileCreationParams({required String uri}) + : this.fromFile(File.fromUri(Uri.parse(uri))); - /// Constructs an [IOXFileCreationParams] from a [File]. - IOXFileCreationParams.fromFile(this.file) : super(uri: file.uri.toString()); + /// Constructs an [IOFileSystemXFileCreationParams] from a [File]. + IOFileSystemXFileCreationParams.fromFile(this.file) : super(uri: file.uri.toString()); - /// Constructs an [IOXFileCreationParams] from a [PlatformXFileCreationParams]. - factory IOXFileCreationParams.fromCreationParams(PlatformXFileCreationParams params) { - return IOXFileCreationParams(uri: params.uri); + /// Constructs an [IOFileSystemXFileCreationParams] from a [PlatformXFileCreationParams]. + factory IOFileSystemXFileCreationParams.fromCreationParams(PlatformXFileCreationParams params) { + return IOFileSystemXFileCreationParams(uri: params.uri); } - /// The underlying [File] for [IOXFile]. + /// The underlying [File] for [IOFileSystemXFile]. final File file; } /// Implementation of [PlatformXFile] for dart:io. -base class IOXFile extends PlatformXFile with IOXFileExtension { - /// Constructs an [IOXFile]. - IOXFile(super.params) : super.implementation(); +base class IOFileSystemXFile extends PlatformXFile with IOFileSystemXFileExtension { + /// Constructs an [IOFileSystemXFile]. + IOFileSystemXFile(super.params); @override - late final IOXFileCreationParams params = super.params is IOXFileCreationParams - ? super.params as IOXFileCreationParams - : IOXFileCreationParams.fromCreationParams(super.params); + late final IOFileSystemXFileCreationParams params = + super.params is IOFileSystemXFileCreationParams + ? super.params as IOFileSystemXFileCreationParams + : IOFileSystemXFileCreationParams.fromCreationParams(super.params); @override File get file => params.file; @@ -78,8 +80,8 @@ base class IOXFile extends PlatformXFile with IOXFileExtension { Future name() async => path.basename(file.path); } -/// Provides platform-specific features for [IOXFile]. -mixin IOXFileExtension implements PlatformXFileExtension { +/// Provides platform-specific features for [IOFileSystemXFile]. +mixin IOFileSystemXFileExtension implements PlatformFileSystemXFileExtension { /// The underlying file. File get file; } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart index 000f99f1009a..a55e97556716 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart @@ -40,7 +40,7 @@ import '../platform_cross_directory.dart'; @immutable base class PlatformFileSystemXDirectoryCreationParams extends PlatformXDirectoryCreationParams { /// Constructs a [PlatformFileSystemXDirectoryCreationParams]. - const PlatformFileSystemXDirectoryCreationParams({required super.uri}); + const PlatformFileSystemXDirectoryCreationParams(String path) : super(uri: path); } /// Base mixin used to provide platform-specific features for implementations of diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart index ed4c2c45cf5c..a8803497e520 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart @@ -40,7 +40,7 @@ import '../platform_cross_file.dart'; @immutable base class PlatformFileSystemXFileCreationParams extends PlatformXFileCreationParams { /// Constructs a [PlatformFileSystemXFileCreationParams]. - const PlatformFileSystemXFileCreationParams({required super.uri}); + const PlatformFileSystemXFileCreationParams(String path) : super(uri: path); } /// Base mixin used to provide platform-specific features for implementations of diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 8fd5f8a0c057..2ff40fd1aa51 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -13,9 +13,7 @@ void main() { expect( await platform - .createPlatformFileSystemXFile( - const PlatformFileSystemXFileCreationParams(uri: 'test'), - ) + .createPlatformFileSystemXFile(const PlatformFileSystemXFileCreationParams('test')) .exists(), false, ); @@ -25,7 +23,7 @@ void main() { final platform = TestCrossFilePlatform(); final PlatformFileSystemXFile file = platform.createPlatformFileSystemXFile( - const PlatformFileSystemXFileCreationParams(uri: 'test'), + const PlatformFileSystemXFileCreationParams('test'), ); // Ensures the error is caught and added to the stream. @@ -38,27 +36,23 @@ void main() { expect( await platform .createPlatformFileSystemXDirectory( - const PlatformFileSystemXDirectoryCreationParams(uri: 'test'), + const PlatformFileSystemXDirectoryCreationParams('test'), ) .exists(), false, ); }); - test( - '_DefaultFileSystemXDirectory.list should throw error by adding it to stream', - () async { - final platform = TestCrossFilePlatform(); + test('_DefaultFileSystemXDirectory.list should throw error by adding it to stream', () async { + final platform = TestCrossFilePlatform(); - final PlatformFileSystemXDirectory dir = platform - .createPlatformFileSystemXDirectory( - const PlatformFileSystemXDirectoryCreationParams(uri: 'test'), - ); + final PlatformFileSystemXDirectory dir = platform.createPlatformFileSystemXDirectory( + const PlatformFileSystemXDirectoryCreationParams('test'), + ); - // Ensures the error is caught and added to the stream. - await expectLater(dir.list(ListParams()).drain, throwsUnsupportedError); - }, - ); + // Ensures the error is caught and added to the stream. + await expectLater(dir.list(ListParams()).drain, throwsUnsupportedError); + }); }); group('ScopedStorage', () { From d33f09371af12efec630448dad6870fbf4fc0b52 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:47:25 -0400 Subject: [PATCH 376/398] update interface to handle paths --- packages/cross_file/cross_file/lib/src/cross_file.dart | 2 ++ packages/cross_file/cross_file_io/lib/src/io_cross_file.dart | 4 ++-- .../lib/src/file_system/platform_file_system_cross_file.dart | 5 ++++- .../test/cross_file_platform_test.dart | 4 ++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index c5ceb6289e89..5179cb63b8d5 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -10,6 +10,8 @@ import 'package:flutter/foundation.dart' show immutable, internal; import 'cross_entity.dart'; +// TODO: Ensure filesytem handles file:// and output consistently + /// A reference to a local data resource. /// /// ## Platform-Specific Features diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart index b7fa43efc007..3d6d19861b7d 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart @@ -14,8 +14,8 @@ import 'package:path/path.dart' as path; @immutable base class IOFileSystemXFileCreationParams extends PlatformFileSystemXFileCreationParams { /// Constructs an [IOFileSystemXFileCreationParams]. - IOFileSystemXFileCreationParams({required String uri}) - : this.fromFile(File.fromUri(Uri.parse(uri))); + IOFileSystemXFileCreationParams(String path) + : this.fromFile(File(path)); /// Constructs an [IOFileSystemXFileCreationParams] from a [File]. IOFileSystemXFileCreationParams.fromFile(this.file) : super(uri: file.uri.toString()); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart index a8803497e520..1220e47ad57a 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart @@ -40,7 +40,7 @@ import '../platform_cross_file.dart'; @immutable base class PlatformFileSystemXFileCreationParams extends PlatformXFileCreationParams { /// Constructs a [PlatformFileSystemXFileCreationParams]. - const PlatformFileSystemXFileCreationParams(String path) : super(uri: path); + PlatformFileSystemXFileCreationParams(String path) : super(uri: Uri.file(path).toString()); } /// Base mixin used to provide platform-specific features for implementations of @@ -92,4 +92,7 @@ abstract base class PlatformFileSystemXFile extends PlatformXFile { @override PlatformFileSystemXFileCreationParams get params => super.params as PlatformFileSystemXFileCreationParams; + + /// The path of the file. + String get path => Uri.parse(params.uri).path; } diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 2ff40fd1aa51..f91cf6014f6b 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -13,7 +13,7 @@ void main() { expect( await platform - .createPlatformFileSystemXFile(const PlatformFileSystemXFileCreationParams('test')) + .createPlatformFileSystemXFile(PlatformFileSystemXFileCreationParams('test')) .exists(), false, ); @@ -23,7 +23,7 @@ void main() { final platform = TestCrossFilePlatform(); final PlatformFileSystemXFile file = platform.createPlatformFileSystemXFile( - const PlatformFileSystemXFileCreationParams('test'), + PlatformFileSystemXFileCreationParams('test'), ); // Ensures the error is caught and added to the stream. From 67b39aa67556dc537de5901848647b5543d30744 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 12:51:45 -0400 Subject: [PATCH 377/398] add path to directory as well --- .../file_system/platform_file_system_cross_directory.dart | 5 ++++- .../test/cross_file_platform_test.dart | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart index a55e97556716..f92801b85768 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart @@ -40,7 +40,7 @@ import '../platform_cross_directory.dart'; @immutable base class PlatformFileSystemXDirectoryCreationParams extends PlatformXDirectoryCreationParams { /// Constructs a [PlatformFileSystemXDirectoryCreationParams]. - const PlatformFileSystemXDirectoryCreationParams(String path) : super(uri: path); + PlatformFileSystemXDirectoryCreationParams(String path) : super(uri: Uri.file(path).toString()); } /// Base mixin used to provide platform-specific features for implementations of @@ -93,4 +93,7 @@ abstract base class PlatformFileSystemXDirectory extends PlatformXDirectory { @override PlatformFileSystemXDirectoryCreationParams get params => super.params as PlatformFileSystemXDirectoryCreationParams; + + /// The path of the directory. + String get path => Uri.parse(params.uri).path; } diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index f91cf6014f6b..52d284532729 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -36,7 +36,7 @@ void main() { expect( await platform .createPlatformFileSystemXDirectory( - const PlatformFileSystemXDirectoryCreationParams('test'), + PlatformFileSystemXDirectoryCreationParams('test'), ) .exists(), false, @@ -47,7 +47,7 @@ void main() { final platform = TestCrossFilePlatform(); final PlatformFileSystemXDirectory dir = platform.createPlatformFileSystemXDirectory( - const PlatformFileSystemXDirectoryCreationParams('test'), + PlatformFileSystemXDirectoryCreationParams('test'), ); // Ensures the error is caught and added to the stream. From 982e3f048eee0e042d7d2ad7d5e2ab2eecf5aac1 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 13:17:01 -0400 Subject: [PATCH 378/398] update io implementation to use file system implementation --- .../integration_test/cross_file_io_test.dart | 8 +- .../cross_file_io/lib/cross_file_io.dart | 6 +- .../cross_file_io/lib/src/cross_file_io.dart | 14 ++-- .../lib/src/io_cross_directory.dart | 67 ----------------- .../src/io_file_system_cross_directory.dart | 73 +++++++++++++++++++ ...le.dart => io_file_system_cross_file.dart} | 21 +++--- .../test/io_cross_directory_test.dart | 8 +- .../test/io_cross_file_test.dart | 14 ++-- .../platform_file_system_cross_directory.dart | 8 +- .../platform_file_system_cross_file.dart | 8 +- 10 files changed, 119 insertions(+), 108 deletions(-) delete mode 100644 packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart create mode 100644 packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart rename packages/cross_file/cross_file_io/lib/src/{io_cross_file.dart => io_file_system_cross_file.dart} (76%) diff --git a/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart b/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart index 8f654f271fd0..d07043339c43 100644 --- a/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart +++ b/packages/cross_file/cross_file_io/example/integration_test/cross_file_io_test.dart @@ -17,13 +17,13 @@ void main() { testWidgets('Can read from file using dart:io implementation', (WidgetTester tester) async { final Directory dir = await getApplicationCacheDirectory(); - final xDir = PlatformXDirectory(PlatformXDirectoryCreationParams(uri: dir.uri.toString())); + final xDir = PlatformFileSystemXDirectory(PlatformFileSystemXDirectoryCreationParams(dir.path)); expect(await xDir.exists(), isTrue); - final file = PlatformXFile( - PlatformXFileCreationParams(uri: path.join(dir.uri.toString(), 'hello.txt')), + final file = PlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams(path.join(dir.path, 'hello.txt')), ); - (file.extension! as IOXFileExtension).file + (file.extension! as IOFileSystemXFileExtension).file ..createSync() ..writeAsStringSync('Hello, World!'); diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index 7b9795bcbfec..ca19e6f9b6f0 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -6,5 +6,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformXDirectoryCreationParams, PlatformXFileCreationParams; export 'src/cross_file_io.dart'; -export 'src/io_cross_directory.dart' show IOXDirectoryCreationParams, IOXDirectoryExtension; -export 'src/io_cross_file.dart' show IOXFileCreationParams, IOXFileExtension; +export 'src/io_file_system_cross_directory.dart' + show IOFileSystemXDirectoryCreationParams, IOFileSystemXDirectoryExtension; +export 'src/io_file_system_cross_file.dart' + show IOFileSystemXFileCreationParams, IOFileSystemXFileExtension; diff --git a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart index 40753d920f91..957cca425962 100644 --- a/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/src/cross_file_io.dart @@ -4,8 +4,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'io_cross_directory.dart'; -import 'io_cross_file.dart'; +import 'io_file_system_cross_directory.dart'; +import 'io_file_system_cross_file.dart'; /// Implementation of [CrossFilePlatform] for dart:io. base class CrossFileIO extends CrossFilePlatform { @@ -15,12 +15,14 @@ base class CrossFileIO extends CrossFilePlatform { } @override - IOXFile createPlatformXFile(PlatformXFileCreationParams params) { - return IOXFile(params); + IOFileSystemXFile createPlatformFileSystemXFile(PlatformFileSystemXFileCreationParams params) { + return IOFileSystemXFile(params); } @override - IOXDirectory createPlatformXDirectory(PlatformXDirectoryCreationParams params) { - return IOXDirectory(params); + IOFileSystemXDirectory createPlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams params, + ) { + return IOFileSystemXDirectory(params); } } diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart deleted file mode 100644 index c7e3890e9c7d..000000000000 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_directory.dart +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:io'; - -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart' show immutable; - -import 'io_cross_file.dart'; - -/// Implementation of [PlatformXDirectoryCreationParams] for dart:io. -@immutable -base class IOXDirectoryCreationParams extends PlatformXDirectoryCreationParams { - /// Constructs an [IOXDirectoryCreationParams]. - IOXDirectoryCreationParams({required String uri}) - : this.fromDirectory(Directory.fromUri(Uri.parse(uri))); - - /// Constructs an [IOXDirectoryCreationParams] from a [Directory]. - IOXDirectoryCreationParams.fromDirectory(this.directory) : super(uri: directory.uri.toString()); - - /// Constructs an [IOXDirectoryCreationParams] from a [PlatformXDirectoryCreationParams]. - factory IOXDirectoryCreationParams.fromCreationParams(PlatformXDirectoryCreationParams params) { - return IOXDirectoryCreationParams(uri: params.uri); - } - - /// The underlying [Directory] for [IOXDirectory]. - final Directory directory; -} - -/// Implementation of [PlatformXDirectory] for dart:io. -base class IOXDirectory extends PlatformXDirectory with IOXDirectoryExtension { - /// Constructs an [IOXDirectory]. - IOXDirectory(super.params); - - @override - late final IOXDirectoryCreationParams params = super.params is IOXDirectoryCreationParams - ? super.params as IOXDirectoryCreationParams - : IOXDirectoryCreationParams.fromCreationParams(super.params); - - @override - Directory get directory => params.directory; - - @override - IOXDirectoryExtension? get extension => this; - - @override - Future exists() async => directory.existsSync(); - - @override - Stream list(ListParams params) async* { - await for (final FileSystemEntity entity in directory.list()) { - switch (entity) { - case final Directory directory: - yield IOXDirectory(IOXDirectoryCreationParams.fromDirectory(directory)); - case final File file: - yield IOXFile(IOXFileCreationParams.fromFile(file)); - } - } - } -} - -/// Provides platform-specific features for [IOXDirectory]. -mixin IOXDirectoryExtension implements PlatformXDirectoryExtension { - /// The underlying directory. - Directory get directory; -} diff --git a/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart new file mode 100644 index 000000000000..33a2f43d2d1a --- /dev/null +++ b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart @@ -0,0 +1,73 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:io'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart' show immutable; + +import 'io_file_system_cross_file.dart'; + +/// Implementation of [PlatformFileSystemXDirectoryCreationParams] for dart:io. +@immutable +base class IOFileSystemXDirectoryCreationParams extends PlatformFileSystemXDirectoryCreationParams { + /// Constructs an [IOFileSystemXDirectoryCreationParams]. + IOFileSystemXDirectoryCreationParams(String path) : this.fromDirectory(Directory(path)); + + /// Constructs an [IOFileSystemXDirectoryCreationParams] from a [Directory]. + IOFileSystemXDirectoryCreationParams.fromDirectory(this.directory) : super(directory.path); + + /// Constructs an [IOFileSystemXDirectoryCreationParams] from a + /// [PlatformFileSystemXDirectoryCreationParams]. + factory IOFileSystemXDirectoryCreationParams.fromCreationParams( + PlatformFileSystemXDirectoryCreationParams params, + ) { + return IOFileSystemXDirectoryCreationParams(params.path); + } + + /// The underlying [Directory] for [IOFileSystemXDirectory]. + final Directory directory; +} + +/// Implementation of [PlatformFileSystemXDirectory] for dart:io. +base class IOFileSystemXDirectory extends PlatformFileSystemXDirectory + with IOFileSystemXDirectoryExtension { + /// Constructs an [IOFileSystemXDirectory]. + IOFileSystemXDirectory(super.params) : super.implementation(); + + @override + late final IOFileSystemXDirectoryCreationParams params = + super.params is IOFileSystemXDirectoryCreationParams + ? super.params as IOFileSystemXDirectoryCreationParams + : IOFileSystemXDirectoryCreationParams.fromCreationParams(super.params); + + @override + Directory get directory => params.directory; + + @override + IOFileSystemXDirectoryExtension? get extension => this; + + @override + Future exists() async => directory.existsSync(); + + @override + Stream list(ListParams params) async* { + await for (final FileSystemEntity entity in directory.list()) { + switch (entity) { + case final Directory directory: + yield IOFileSystemXDirectory( + IOFileSystemXDirectoryCreationParams.fromDirectory(directory), + ); + case final File file: + yield IOFileSystemXFile(IOFileSystemXFileCreationParams.fromFile(file)); + } + } + } +} + +/// Provides platform-specific features for [IOFileSystemXDirectory]. +mixin IOFileSystemXDirectoryExtension implements PlatformFileSystemXDirectoryExtension { + /// The underlying directory. + Directory get directory; +} diff --git a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart similarity index 76% rename from packages/cross_file/cross_file_io/lib/src/io_cross_file.dart rename to packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart index 3d6d19861b7d..2bfc95b04b05 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart @@ -14,25 +14,26 @@ import 'package:path/path.dart' as path; @immutable base class IOFileSystemXFileCreationParams extends PlatformFileSystemXFileCreationParams { /// Constructs an [IOFileSystemXFileCreationParams]. - IOFileSystemXFileCreationParams(String path) - : this.fromFile(File(path)); + IOFileSystemXFileCreationParams(String path) : this.fromFile(File(path)); /// Constructs an [IOFileSystemXFileCreationParams] from a [File]. - IOFileSystemXFileCreationParams.fromFile(this.file) : super(uri: file.uri.toString()); + IOFileSystemXFileCreationParams.fromFile(this.file) : super(file.path); - /// Constructs an [IOFileSystemXFileCreationParams] from a [PlatformXFileCreationParams]. - factory IOFileSystemXFileCreationParams.fromCreationParams(PlatformXFileCreationParams params) { - return IOFileSystemXFileCreationParams(uri: params.uri); + /// Constructs an [IOFileSystemXFileCreationParams] from a [PlatformFileSystemXFileCreationParams]. + factory IOFileSystemXFileCreationParams.fromCreationParams( + PlatformFileSystemXFileCreationParams params, + ) { + return IOFileSystemXFileCreationParams(params.path); } /// The underlying [File] for [IOFileSystemXFile]. final File file; } -/// Implementation of [PlatformXFile] for dart:io. -base class IOFileSystemXFile extends PlatformXFile with IOFileSystemXFileExtension { +/// Implementation of [PlatformFileSystemXFile] for dart:io. +base class IOFileSystemXFile extends PlatformFileSystemXFile with IOFileSystemXFileExtension { /// Constructs an [IOFileSystemXFile]. - IOFileSystemXFile(super.params); + IOFileSystemXFile(super.params) : super.implementation(); @override late final IOFileSystemXFileCreationParams params = @@ -44,7 +45,7 @@ base class IOFileSystemXFile extends PlatformXFile with IOFileSystemXFileExtensi File get file => params.file; @override - PlatformXFileExtension? get extension => this; + PlatformFileSystemXFileExtension? get extension => this; @override Future lastModified() async { diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart index b4c2636bd0d8..9fde0b3a0aa4 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -18,16 +18,16 @@ void main() { }); test('exists', () async { - final directory = PlatformXDirectory( - PlatformXDirectoryCreationParams(uri: testDirectory.uri.toString()), + final directory = PlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams(testDirectory.path), ); expect(await directory.exists(), testDirectory.existsSync()); }); test('list', () async { - final directory = PlatformXDirectory( - PlatformXDirectoryCreationParams(uri: testDirectory.uri.toString()), + final directory = PlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams(testDirectory.path), ); expect( diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index 07f655b9807e..f4f0114c5bf4 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -18,43 +18,43 @@ void main() { }); test('lastModified', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.lastModified(), testFile.lastModifiedSync()); }); test('length', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.length(), await testFile.length()); }); test('openRead', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.openRead().toList(), await testFile.openRead().toList()); }); test('readAsBytes', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.readAsBytes(), await testFile.readAsBytes()); }); test('readAsString', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.readAsString(), await testFile.readAsString()); }); test('exists', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.exists(), testFile.existsSync()); }); test('name', () async { - final file = PlatformXFile(PlatformXFileCreationParams(uri: testFile.uri.toString())); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(testFile.path)); expect(await file.name(), 'test_file.txt'); }); diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart index f92801b85768..fc3d3ba49d49 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart @@ -40,7 +40,10 @@ import '../platform_cross_directory.dart'; @immutable base class PlatformFileSystemXDirectoryCreationParams extends PlatformXDirectoryCreationParams { /// Constructs a [PlatformFileSystemXDirectoryCreationParams]. - PlatformFileSystemXDirectoryCreationParams(String path) : super(uri: Uri.file(path).toString()); + PlatformFileSystemXDirectoryCreationParams(this.path) : super(uri: Uri.file(path).toString()); + + /// The path of the directory. + final String path; } /// Base mixin used to provide platform-specific features for implementations of @@ -93,7 +96,4 @@ abstract base class PlatformFileSystemXDirectory extends PlatformXDirectory { @override PlatformFileSystemXDirectoryCreationParams get params => super.params as PlatformFileSystemXDirectoryCreationParams; - - /// The path of the directory. - String get path => Uri.parse(params.uri).path; } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart index 1220e47ad57a..54685a800822 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart @@ -40,7 +40,10 @@ import '../platform_cross_file.dart'; @immutable base class PlatformFileSystemXFileCreationParams extends PlatformXFileCreationParams { /// Constructs a [PlatformFileSystemXFileCreationParams]. - PlatformFileSystemXFileCreationParams(String path) : super(uri: Uri.file(path).toString()); + PlatformFileSystemXFileCreationParams(this.path) : super(uri: Uri.file(path).toString()); + + /// The path of the file. + final String path; } /// Base mixin used to provide platform-specific features for implementations of @@ -92,7 +95,4 @@ abstract base class PlatformFileSystemXFile extends PlatformXFile { @override PlatformFileSystemXFileCreationParams get params => super.params as PlatformFileSystemXFileCreationParams; - - /// The path of the file. - String get path => Uri.parse(params.uri).path; } From c6c12ddec5f194f3cb7fc7e4f0d346d6fbcaf13f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 13:40:30 -0400 Subject: [PATCH 379/398] change android and ios to create an instance of io to create file system --- .../lib/src/cross_file_android.dart | 16 ++++++++++++- .../cross_file_darwin_test.dart | 23 ++++++++++++++++--- .../cross_file_darwin/example/pubspec.yaml | 2 ++ .../lib/src/cross_file_darwin.dart | 16 ++++++++++++- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart index b3b6c47a5017..fc6af34a8b6f 100644 --- a/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/src/cross_file_android.dart @@ -9,12 +9,26 @@ import 'android_scoped_storage_cross_directory.dart'; import 'android_scoped_storage_cross_file.dart'; /// Implementation of [CrossFilePlatform] for Android. -base class CrossFileAndroid extends CrossFileIO { +base class CrossFileAndroid extends CrossFilePlatform { /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileAndroid(); } + @override + PlatformFileSystemXFile createPlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams params, + ) { + return CrossFileIO().createPlatformFileSystemXFile(params); + } + + @override + PlatformFileSystemXDirectory createPlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams params, + ) { + return CrossFileIO().createPlatformFileSystemXDirectory(params); + } + @override AndroidScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, diff --git a/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart b/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart index 621977be68c7..26a1530a22c4 100644 --- a/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart +++ b/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart @@ -2,13 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - // Since this test is lacking integration tests, this test ensures the example - // app can be launched on an emulator/device. - testWidgets('Launch Test', (WidgetTester tester) async {}); + testWidgets('Can read from file using dart:io implementation', (WidgetTester tester) async { + final Directory dir = await getApplicationCacheDirectory(); + + final xDir = PlatformFileSystemXDirectory(PlatformFileSystemXDirectoryCreationParams(dir.path)); + expect(await xDir.exists(), isTrue); + + final file = PlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams(path.join(dir.path, 'hello.txt')), + ); + (file.extension! as IOFileSystemXFileExtension).file + ..createSync() + ..writeAsStringSync('Hello, World!'); + + expect(await file.readAsString(), 'Hello, World!'); + }); } diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 592134920cca..06dd7d2d88c1 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -28,6 +28,8 @@ dev_dependencies: sdk: flutter integration_test: sdk: flutter + path: ^1.9.1 + path_provider: ^2.1.6 flutter: uses-material-design: true diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart index f00f2dc02852..bf8479c83ad5 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin.dart @@ -9,12 +9,26 @@ import 'darwin_scoped_storage_cross_directory.dart'; import 'darwin_scoped_storage_cross_file.dart'; /// Implementation of [CrossFilePlatform] for iOS and macOS. -base class CrossFileDarwin extends CrossFileIO { +base class CrossFileDarwin extends CrossFilePlatform { /// Registers this class as the default instance of [CrossFilePlatform]. static void registerWith() { CrossFilePlatform.instance = CrossFileDarwin(); } + @override + PlatformFileSystemXFile createPlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams params, + ) { + return CrossFileIO().createPlatformFileSystemXFile(params); + } + + @override + PlatformFileSystemXDirectory createPlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams params, + ) { + return CrossFileIO().createPlatformFileSystemXDirectory(params); + } + @override DarwinScopedStorageXFile createPlatformScopedStorageXFile( PlatformScopedStorageXFileCreationParams params, From 1d884a5d034bd69224f051eec1e5ddfc89c686ef Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 15:04:32 -0400 Subject: [PATCH 380/398] add io test for android and ios --- .../cross_file_android_test.dart | 24 ++++++++++++++++--- .../cross_file_android/example/pubspec.yaml | 5 ++++ .../cross_file_darwin_test.dart | 1 + .../cross_file_darwin/example/pubspec.yaml | 3 +++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_android/example/integration_test/cross_file_android_test.dart b/packages/cross_file/cross_file_android/example/integration_test/cross_file_android_test.dart index 621977be68c7..d07043339c43 100644 --- a/packages/cross_file/cross_file_android/example/integration_test/cross_file_android_test.dart +++ b/packages/cross_file/cross_file_android/example/integration_test/cross_file_android_test.dart @@ -2,13 +2,31 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + +import 'package:cross_file_io/cross_file_io.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; +import 'package:path/path.dart' as path; +import 'package:path_provider/path_provider.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - // Since this test is lacking integration tests, this test ensures the example - // app can be launched on an emulator/device. - testWidgets('Launch Test', (WidgetTester tester) async {}); + testWidgets('Can read from file using dart:io implementation', (WidgetTester tester) async { + final Directory dir = await getApplicationCacheDirectory(); + + final xDir = PlatformFileSystemXDirectory(PlatformFileSystemXDirectoryCreationParams(dir.path)); + expect(await xDir.exists(), isTrue); + + final file = PlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams(path.join(dir.path, 'hello.txt')), + ); + (file.extension! as IOFileSystemXFileExtension).file + ..createSync() + ..writeAsStringSync('Hello, World!'); + + expect(await file.readAsString(), 'Hello, World!'); + }); } diff --git a/packages/cross_file/cross_file_android/example/pubspec.yaml b/packages/cross_file/cross_file_android/example/pubspec.yaml index ee446f16a758..8e3b142b8f97 100644 --- a/packages/cross_file/cross_file_android/example/pubspec.yaml +++ b/packages/cross_file/cross_file_android/example/pubspec.yaml @@ -23,11 +23,16 @@ dependencies: mime: ^2.0.0 dev_dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_io` is released. + cross_file_io: + path: ../../../cross_file/cross_file_io espresso: ^0.4.0 flutter_test: sdk: flutter integration_test: sdk: flutter + path: ^1.9.1 + path_provider: ^2.1.6 flutter: uses-material-design: true diff --git a/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart b/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart index 26a1530a22c4..d07043339c43 100644 --- a/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart +++ b/packages/cross_file/cross_file_darwin/example/integration_test/cross_file_darwin_test.dart @@ -4,6 +4,7 @@ import 'dart:io'; +import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; diff --git a/packages/cross_file/cross_file_darwin/example/pubspec.yaml b/packages/cross_file/cross_file_darwin/example/pubspec.yaml index 06dd7d2d88c1..2c6a7aca5dc8 100644 --- a/packages/cross_file/cross_file_darwin/example/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/example/pubspec.yaml @@ -24,6 +24,9 @@ dependencies: mime: ^2.0.0 dev_dependencies: + # TODO(bparrishMines): Change this to hosted dependency once `cross_file_io` is released. + cross_file_io: + path: ../../../cross_file/cross_file_io flutter_test: sdk: flutter integration_test: From b6dee66bce8a1430d2a6c67f11d51fee3516e96b Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:13:38 -0400 Subject: [PATCH 381/398] add file system to app facing --- .../cross_file/cross_file/lib/cross_file.dart | 4 +- .../cross_file/lib/src/cross_directory.dart | 85 +++---------------- .../cross_file/lib/src/cross_entity.dart | 5 +- .../cross_file/lib/src/cross_file.dart | 64 +------------- .../file_system_cross_directory.dart | 82 ++++++++++++++++++ .../file_system/file_system_cross_file.dart | 80 +++++++++++++++++ .../scoped_storage_cross_directory.dart | 25 +++--- .../scoped_storage_cross_file.dart | 29 +++++-- .../lib/cross_file_android.dart | 4 +- .../lib/cross_file_darwin.dart | 4 +- .../cross_file_io/lib/cross_file_io.dart | 7 +- .../platform_file_system_cross_directory.dart | 2 +- ...atform_scoped_storage_cross_directory.dart | 4 +- .../cross_file_web/lib/cross_file_web.dart | 4 +- 14 files changed, 235 insertions(+), 164 deletions(-) create mode 100644 packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart create mode 100644 packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart rename packages/cross_file/cross_file/lib/src/{ => scoped_storage}/scoped_storage_cross_directory.dart (83%) rename packages/cross_file/cross_file/lib/src/{ => scoped_storage}/scoped_storage_cross_file.dart (78%) diff --git a/packages/cross_file/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart index 571863764873..7afba15ff6e0 100644 --- a/packages/cross_file/cross_file/lib/cross_file.dart +++ b/packages/cross_file/cross_file/lib/cross_file.dart @@ -7,8 +7,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart export 'src/cross_directory.dart'; export 'src/cross_entity.dart'; export 'src/cross_file.dart'; -export 'src/scoped_storage_cross_directory.dart'; -export 'src/scoped_storage_cross_file.dart'; +export 'src/scoped_storage/scoped_storage_cross_directory.dart'; +export 'src/scoped_storage/scoped_storage_cross_file.dart'; /// Provides top level functions for the `cross_file` package. final class CrossFile { diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index e825ef46ca3b..fc72372b4563 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -3,77 +3,21 @@ // found in the LICENSE file. import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart' show immutable, internal; +import 'package:flutter/foundation.dart' show immutable, internal, protected; import 'cross_entity.dart'; -import 'cross_file.dart'; -import 'scoped_storage_cross_directory.dart'; -import 'scoped_storage_cross_file.dart'; +import 'scoped_storage/scoped_storage_cross_directory.dart'; +import 'scoped_storage/scoped_storage_cross_file.dart'; /// A reference to a container of local data resources. /// /// Note: Not all platforms support accessing directories. -/// -/// ## Platform-Specific Features -/// This class contains an underlying implementation provided by the current -/// platform. Once a platform implementation is imported, the examples below -/// can be followed to use features provided by a platform's implementation. -/// -/// {@macro cross_file.XDirectory.fromCreationParams} -/// -/// Below is an example of accessing the platform-specific extension for -/// the dart:io implementation of `cross_file`: -/// -/// ```dart -/// final XDirectory dir = XDirectory.fromUri(Uri.directory('/my/docs/.')); -/// -/// final IOXDirectoryExtension? ioExtension = file.maybeGetExtension(); -/// if (ioExtension != null) { -/// print(ioExtension.directory.path); -/// } -/// ``` @immutable -base class XDirectory extends XEntity { - /// Constructs a [XDirectory]. - /// - /// See [XDirectory.fromCreationParams] for setting parameters for a specific - /// platform. - XDirectory({required String uri}) - : this.fromCreationParams(PlatformXDirectoryCreationParams(uri: uri)); - - /// Constructs a [XDirectory]. - /// - /// See [XDirectory.fromCreationParams] for setting parameters for a specific - /// platform. - XDirectory.fromUri(Uri uri) : this(uri: uri.toString()); - - /// Constructs a [XDirectory] from a path. - XDirectory.fromPath(String path) : this.fromUri(Uri.directory(path)); - - /// Constructs a [XDirectory] from creation params for a specific platform. - /// - /// {@template cross_file.XDirectory.fromCreationParams} - /// Below is an example of setting platform-specific creation parameters for - /// the dart:io implementation of `cross_file`: - /// - /// ```dart - /// var params = const PlatformXDirectoryCreationParams(uri: 'file:///my/docs/'); - /// - /// if (CrossFilePlatform.instance is CrossFileIO) { - /// params = IOXDirectoryCreationParams.fromCreationParams( - /// params, - /// ); - /// } - /// - /// final dir = XDirectory.fromCreationParams(params); - /// ``` - /// {@endtemplate} - XDirectory.fromCreationParams(PlatformXDirectoryCreationParams params) - : this.fromPlatform(PlatformXDirectory(params)); - +abstract base class XDirectory extends XEntity { /// Constructs a [XDirectory] from a specific platform implementation. @internal - const XDirectory.fromPlatform(PlatformXDirectory super.platform); + @protected + const XDirectory(PlatformXDirectory super.platform); /// Implementation of [PlatformXDirectory] for the current platform. @internal @@ -85,22 +29,13 @@ base class XDirectory extends XEntity { // Converts PlatformXEntities to XEntities. return platform.list(ListParams()).map((PlatformXEntity entity) { switch (entity) { - case PlatformXFile(): - if (entity case PlatformScopedStorageXFile()) { - return ScopedStorageXFile.fromPlatform(entity); - } - return XFile.fromPlatform(entity); - case PlatformXDirectory(): - if (entity case PlatformScopedStorageXDirectory()) { - return ScopedStorageXDirectory.fromPlatform(entity); - } - return XDirectory.fromPlatform(entity); + case PlatformScopedStorageXFile(): + return ScopedStorageXFile.fromPlatform(entity); + case PlatformScopedStorageXDirectory(): + return ScopedStorageXDirectory.fromPlatform(entity); } return XEntity(entity); }); } - - @override - String toString() => platform.params.uri; } diff --git a/packages/cross_file/cross_file/lib/src/cross_entity.dart b/packages/cross_file/cross_file/lib/src/cross_entity.dart index 0d0bf532d91e..8747482d2d2a 100644 --- a/packages/cross_file/cross_file/lib/src/cross_entity.dart +++ b/packages/cross_file/cross_file/lib/src/cross_entity.dart @@ -9,8 +9,8 @@ import 'package:flutter/foundation.dart' show immutable, internal, protected; @immutable base class XEntity { /// Constructs a [XEntity]. - @protected @internal + @protected const XEntity(this.platform); /// Implementation of [XEntity] for the current platform. @@ -29,4 +29,7 @@ base class XEntity { /// Whether the resource represented by this reference exists. Future exists() => platform.exists(); + + @override + String toString() => platform.params.uri; } diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index 5179cb63b8d5..f0abbb755e03 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -6,70 +6,17 @@ import 'dart:convert'; import 'dart:typed_data'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter/foundation.dart' show immutable, internal; +import 'package:flutter/foundation.dart' show immutable, internal, protected; import 'cross_entity.dart'; -// TODO: Ensure filesytem handles file:// and output consistently - /// A reference to a local data resource. -/// -/// ## Platform-Specific Features -/// This class contains an underlying implementation provided by the current -/// platform. Once a platform implementation is imported, the examples below -/// can be followed to use features provided by a platform's implementation. -/// -/// {@macro cross_file.XFile.fromCreationParams} -/// -/// Below is an example of accessing the platform-specific extension for -/// the dart:io implementation of `cross_file`: -/// -/// ```dart -/// final XFile file = XFile.fromUri(Uri.file('/my/file.txt')); -/// -/// final IOXFileExtension? ioExtension = file.maybeGetExtension(); -/// if (ioExtension != null) { -/// print(ioExtension.file.path); -/// } -/// ``` @immutable -base class XFile extends XEntity { - /// Constructs a [XFile]. - /// - /// See [XFile.fromCreationParams] for setting parameters for a specific - /// platform. - XFile({required String uri}) : this.fromCreationParams(PlatformXFileCreationParams(uri: uri)); - - /// Constructs a [XFile] from a [Uri]. - XFile.fromUri(Uri uri) : this(uri: uri.toString()); - - /// Constructs a [XFile] from a file path. - XFile.fromPath(String path) : this.fromUri(Uri.file(path)); - - /// Constructs a [XFile] from creation params for a specific platform. - /// - /// {@template cross_file.XFile.fromCreationParams} - /// Below is an example of setting platform-specific creation parameters for - /// the dart:io implementation of `cross_file`: - /// - /// ```dart - /// var params = const PlatformXFileCreationParams(uri: 'file:///my/file.txt'); - /// - /// if (CrossFilePlatform.instance is CrossFileIO) { - /// params = IOXFileCreationParams.fromCreationParams( - /// params, - /// ); - /// } - /// - /// final file = XFile.fromCreationParams(params); - /// ``` - /// {@endtemplate} - XFile.fromCreationParams(PlatformXFileCreationParams params) - : this.fromPlatform(PlatformXFile(params)); - +abstract base class XFile extends XEntity { /// Constructs a [XFile] from a specific platform implementation. @internal - const XFile.fromPlatform(PlatformXFile super.platform); + @protected + const XFile(PlatformXFile super.platform); /// Implementation of [XFile] for the current platform. @internal @@ -126,7 +73,4 @@ base class XFile extends XEntity { /// If the file is identified by a path, only the base name of the file will /// be included in the name. Future name() => platform.name(); - - @override - String toString() => platform.params.uri; } diff --git a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart new file mode 100644 index 000000000000..c67239cdc0d5 --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart @@ -0,0 +1,82 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart' + show TargetPlatform, defaultTargetPlatform, immutable, internal; + +import '../cross_directory.dart'; + +/// A reference to a directory (or folder) on the file system. +/// +/// ## Platform-Specific Features +/// This class contains an underlying implementation provided by the current +/// platform. Once a platform implementation is imported, the examples below +/// can be followed to use features provided by a platform's implementation. +/// +/// {@macro cross_file.FileSystemXDirectory.fromCreationParams} +/// +/// Below is an example of accessing the platform-specific extension for +/// the IO implementation of `cross_file`: +/// +/// ```dart +/// final FileSystemXDirectory dir = FileSystemXDirectory(uri: 'my/dir/'); +/// +/// final IOFileSystemXDirectoryExtension? ioExtension = +/// file.getExtension(); +/// if (ioExtension != null) { +/// print(ioExtension.directory.statSync().accessed); +/// } +/// ``` +@immutable +base class FileSystemXDirectory extends XDirectory { + /// Constructs a [FileSystemXDirectory]. + /// + /// See [FileSystemXDirectory.fromCreationParams] for setting parameters + /// for a specific platform. + FileSystemXDirectory(String path) + : this.fromCreationParams(PlatformFileSystemXDirectoryCreationParams(path)); + + /// Constructs a [FileSystemXDirectory]. + /// + /// See [FileSystemXDirectory.fromCreationParams] for setting parameters + /// for a specific platform. + FileSystemXDirectory.fromUri(Uri uri) + : this(uri.toFilePath(windows: defaultTargetPlatform == TargetPlatform.windows)); + + /// Constructs a [FileSystemXDirectory] from creation params for a specific + /// platform. + /// + /// {@template cross_file.FileSystemXDirectory.fromCreationParams} + /// Below is an example of setting platform-specific creation parameters for + /// the IO implementation of `cross_file`: + /// + /// ```dart + /// late final PlatformFileSystemXDirectoryCreationParams params; + /// + /// switch(CrossFile.implementation) { + /// case CrossFileIO(): + /// params = IOFileSystemXDirectoryCreationParams.fromDirectory( + /// Directory('my/dir/'), + /// ); + /// default: + /// params = PlatformFileSystemXDirectoryCreationParams('my/dir/'); + /// } + /// + /// + /// final dir = FileSystemXDirectory.fromCreationParams(params); + /// ``` + /// {@endtemplate} + FileSystemXDirectory.fromCreationParams(PlatformFileSystemXDirectoryCreationParams params) + : this.fromPlatform(PlatformFileSystemXDirectory(params)); + + /// Constructs a [FileSystemXDirectory] from a specific platform + /// implementation. + @internal + const FileSystemXDirectory.fromPlatform(PlatformFileSystemXDirectory super.platform); + + @internal + @override + PlatformFileSystemXDirectory get platform => super.platform as PlatformFileSystemXDirectory; +} diff --git a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart new file mode 100644 index 000000000000..e304e4519acc --- /dev/null +++ b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart @@ -0,0 +1,80 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter/foundation.dart' + show TargetPlatform, defaultTargetPlatform, immutable, internal; + +import '../cross_file.dart'; + +/// A reference to a local data resource on the file system. +/// +/// ## Platform-Specific Features +/// This class contains an underlying implementation provided by the current +/// platform. Once a platform implementation is imported, the examples below +/// can be followed to use features provided by a platform's implementation. +/// +/// {@macro cross_file.FileSystemXFile.fromCreationParams} +/// +/// Below is an example of accessing the platform-specific extension for +/// the IO implementation of `cross_file`: +/// +/// ```dart +/// final FileSystemXFile file = FileSystemXDirectory('my/file.txt'); +/// +/// final IOFileSystemXFileExtension? ioExtension = +/// file.getExtension(); +/// if (ioExtension != null) { +/// print(ioExtension.file.lastAccessedSync()); +/// } +/// ``` +@immutable +base class FileSystemXFile extends XFile { + /// Constructs a [FileSystemXFile]. + /// + /// See [FileSystemXFile.fromCreationParams] for setting parameters + /// for a specific platform. + FileSystemXFile(String path) + : this.fromCreationParams(PlatformFileSystemXFileCreationParams(path)); + + /// Constructs a [FileSystemXFile]. + /// + /// See [FileSystemXFile.fromCreationParams] for setting parameters for a + /// specific platform. + FileSystemXFile.fromUri(Uri uri) + : this(uri.toFilePath(windows: defaultTargetPlatform == TargetPlatform.windows)); + + /// Constructs a [FileSystemXFile] from creation params for a specific + /// platform. + /// + /// {@template cross_file.FileSystemXFile.fromCreationParams} + /// Below is an example of setting platform-specific creation parameters for + /// the Android implementation of `cross_file`: + /// + /// ```dart + /// late final PlatformFileSystemCreationParams params; + /// + /// switch(CrossFile.implementation) { + /// case CrossFileIO(): + /// params = IOFileSystemXFileCreationParams.fromFile( + /// File('my/file.txt'), + /// ); + /// default: + /// params = PlatformFileSystemXFileCreationParams('my/file.txt'); + /// } + /// + /// final file = FileSystemXFile.fromCreationParams(params); + /// ``` + /// {@endtemplate} + FileSystemXFile.fromCreationParams(PlatformFileSystemXFileCreationParams params) + : this.fromPlatform(PlatformFileSystemXFile(params)); + + /// Constructs a [FileSystemXFile] from a specific platform implementation. + @internal + const FileSystemXFile.fromPlatform(PlatformFileSystemXFile super.platform); + + @internal + @override + PlatformFileSystemXFile get platform => super.platform as PlatformFileSystemXFile; +} diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart b/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_directory.dart similarity index 83% rename from packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart rename to packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_directory.dart index 65851cb56d6a..0a368aad816b 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_directory.dart @@ -5,7 +5,7 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart' show immutable, internal; -import 'cross_directory.dart'; +import '../cross_directory.dart'; /// A reference to a directory (or folder) on the file system within a devices /// scoped storage. @@ -27,7 +27,7 @@ import 'cross_directory.dart'; /// final ScopedStorageXDirectory directory = ScopedStorageXDirectory(uri: 'content://my/dir'); /// /// final AndroidScopedStorageXDirectoryExtension? androidExtension = -/// file.maybeGetExtension(); +/// file.getExtension(); /// if (androidExtension != null) { /// print(androidExtension.name()); /// } @@ -55,15 +55,21 @@ base class ScopedStorageXDirectory extends XDirectory { /// the Android implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformScopedStorageXDirectoryCreationParams(uri: 'content://my/docs'); + /// late final PlatformScopedStorageXDirectoryCreationParams params; /// - /// if (CrossFilePlatform.instance is CrossFileAndroid) { - /// params = AndroidScopedStorageXDirectoryCreationParams.fromCreationParams( - /// params, - /// ); + /// switch(CrossFile.implementation) { + /// case CrossFileAndroid(): + /// params = PlatformScopedStorageXDirectoryCreationParams( + /// uri: 'content://my/file.txt' + /// ); + /// default: + /// params = PlatformScopedStorageXFileCreationParams( + /// uri: 'my/dir/' + /// ); /// } /// - /// final file = ScopedStorageXDirectory.fromCreationParams(params); + /// + /// final dir = ScopedStorageXDirectory.fromCreationParams(params); /// ``` /// {@endtemplate} ScopedStorageXDirectory.fromCreationParams(PlatformScopedStorageXDirectoryCreationParams params) @@ -72,8 +78,7 @@ base class ScopedStorageXDirectory extends XDirectory { /// Constructs a [ScopedStorageXDirectory] from a specific platform /// implementation. @internal - const ScopedStorageXDirectory.fromPlatform(PlatformScopedStorageXDirectory super.platform) - : super.fromPlatform(); + const ScopedStorageXDirectory.fromPlatform(PlatformScopedStorageXDirectory super.platform); @internal @override diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart similarity index 78% rename from packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart rename to packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart index e590e48fd481..0f7ac0efb15f 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart @@ -5,7 +5,10 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart' show immutable, internal; -import 'cross_file.dart'; +import '../cross_file.dart'; + +// TODO: What is scoped storage? in readme. This plugin provides to implementaiton: +// Filesystem vs scoped storage. /// A reference to a local data resource within a device's scoped storage. /// @@ -26,7 +29,7 @@ import 'cross_file.dart'; /// final ScopedStorageXFile file = ScopedStorageXFile(uri: 'content://my/file.txt'); /// /// final AndroidScopedStorageXFileExtension? androidExtension = -/// file.maybeGetExtension(); +/// file.getExtension(); /// if (androidExtension != null) { /// print(androidExtension.name()); /// } @@ -54,12 +57,21 @@ base class ScopedStorageXFile extends XFile { /// the Android implementation of `cross_file`: /// /// ```dart - /// var params = const PlatformScopedStorageXFileCreationParams(uri: 'content://my/file.txt'); + /// late final PlatformScopedStorageCreationParams params; /// - /// if (CrossFilePlatform.instance is CrossFileAndroid) { - /// params = AndroidScopedStorageXFileCreationParams.fromCreationParams( - /// params, - /// ); + /// switch(CrossFile.implementation) { + /// case CrossFileWeb(): + /// params = WebScopedStorageXFileCreationParams.fromObjectUrl( + /// objectUrl: 'blob:https://some/url:for/file', + /// ); + /// case CrossFileAndroid(): + /// params = PlatformScopedStorageXFileCreationParams( + /// uri: 'content://my/file.txt' + /// ); + /// default: + /// params = PlatformScopedStorageXFileCreationParams( + /// uri: 'my/file.txt' + /// ); /// } /// /// final file = ScopedStorageXFile.fromCreationParams(params); @@ -70,8 +82,7 @@ base class ScopedStorageXFile extends XFile { /// Constructs a [ScopedStorageXFile] from a specific platform implementation. @internal - const ScopedStorageXFile.fromPlatform(PlatformScopedStorageXFile super.platform) - : super.fromPlatform(); + const ScopedStorageXFile.fromPlatform(PlatformScopedStorageXFile super.platform); @internal @override diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index 94345d9ccbdb..e579dc00edb0 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -6,6 +6,8 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams; + PlatformScopedStorageXFileCreationParams, + PlatformXDirectoryCreationParams, + PlatformXFileCreationParams; export 'src/cross_file_android.dart'; diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index 1a62385f9fc9..de7151eb129b 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -6,7 +6,9 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams; + PlatformScopedStorageXFileCreationParams, + PlatformXDirectoryCreationParams, + PlatformXFileCreationParams; export 'src/cross_file_darwin.dart'; export 'src/darwin_scoped_storage_cross_directory.dart' diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index ca19e6f9b6f0..dc3b99cc9c8d 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -3,7 +3,12 @@ // found in the LICENSE file. export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show ListParams, PlatformXDirectoryCreationParams, PlatformXFileCreationParams; + show + ListParams, + PlatformFileSystemXDirectoryCreationParams, + PlatformFileSystemXFileCreationParams, + PlatformXDirectoryCreationParams, + PlatformXFileCreationParams; export 'src/cross_file_io.dart'; export 'src/io_file_system_cross_directory.dart' diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart index fc3d3ba49d49..fb856bed4d1a 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_directory.dart @@ -70,7 +70,7 @@ base class PlatformFileSystemXDirectoryCreationParams extends PlatformXDirectory /// ``` mixin PlatformFileSystemXDirectoryExtension implements PlatformXDirectoryExtension {} -/// A reference to a directory (or folder) on the file system. +/// Interface for a reference to a directory (or folder) on the file system. abstract base class PlatformFileSystemXDirectory extends PlatformXDirectory { /// Creates a new [PlatformFileSystemXDirectory] factory PlatformFileSystemXDirectory(PlatformFileSystemXDirectoryCreationParams params) { diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart index c1784742d21d..1b60de06dd1f 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/scoped_storage/platform_scoped_storage_cross_directory.dart @@ -67,8 +67,8 @@ base class PlatformScopedStorageXDirectoryCreationParams extends PlatformXDirect /// ``` mixin PlatformScopedStorageXDirectoryExtension implements PlatformXDirectoryExtension {} -/// A reference to a directory (or folder) on the file system within a device's -/// scoped storage. +/// Interface for a reference to a directory (or folder) on the file system +/// within a device's scoped storage. abstract base class PlatformScopedStorageXDirectory extends PlatformXDirectory { /// Creates a new [PlatformScopedStorageXDirectory] factory PlatformScopedStorageXDirectory(PlatformScopedStorageXDirectoryCreationParams params) { diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index 4d8770337dad..f10bf4927edf 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -6,7 +6,9 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart show ListParams, PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams; + PlatformScopedStorageXFileCreationParams, + PlatformXDirectoryCreationParams, + PlatformXFileCreationParams; export 'src/cross_file_web.dart'; export 'src/web_scoped_storage_cross_file.dart' From 7e2f9a5179f9a82bbb0b06a96f842f7cf2765272 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Fri, 7 Aug 2026 17:31:02 -0400 Subject: [PATCH 382/398] file system implementation in app facing --- .../example/lib/readme_excerpts.dart | 6 +++--- .../cross_file/cross_file/lib/cross_file.dart | 2 ++ .../cross_file/lib/src/cross_directory.dart | 18 ++++++++++++++++++ .../cross_file/lib/src/cross_file.dart | 14 ++++++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart index 054a5d125f9b..3db2e185a6d1 100644 --- a/packages/cross_file/cross_file/example/lib/readme_excerpts.dart +++ b/packages/cross_file/cross_file/example/lib/readme_excerpts.dart @@ -14,7 +14,7 @@ import 'package:flutter/foundation.dart' show debugPrint; /// Demonstrate instantiating an XFile for the README. Future instantiateXFile() async { // #docregion Instantiate - final file = XFile.fromUri(Uri.file('assets/hello.txt')); + final file = XFile.fileSystem(path: 'assets/hello.txt'); debugPrint('File information:'); debugPrint('- URI: ${file.uri}'); @@ -39,11 +39,11 @@ Future accessPlatformFeatures() async { final params = WebScopedStorageXFileCreationParams.fromObjectUrl( objectUrl: 'blob:https://some/url:for/file', ); - file = XFile.fromCreationParams(params); + file = ScopedStorageXFile.fromCreationParams(params); case CrossFileDarwin(): file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); default: - file = XFile.fromUri(Uri.file('/my/file.txt')); + file = XFile.fileSystem(path: '/my/file.txt'); } await file diff --git a/packages/cross_file/cross_file/lib/cross_file.dart b/packages/cross_file/cross_file/lib/cross_file.dart index 7afba15ff6e0..61d564f9778f 100644 --- a/packages/cross_file/cross_file/lib/cross_file.dart +++ b/packages/cross_file/cross_file/lib/cross_file.dart @@ -7,6 +7,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart export 'src/cross_directory.dart'; export 'src/cross_entity.dart'; export 'src/cross_file.dart'; +export 'src/file_system/file_system_cross_directory.dart'; +export 'src/file_system/file_system_cross_file.dart'; export 'src/scoped_storage/scoped_storage_cross_directory.dart'; export 'src/scoped_storage/scoped_storage_cross_file.dart'; diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index fc72372b4563..f4de1651e50e 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -6,6 +6,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'package:flutter/foundation.dart' show immutable, internal, protected; import 'cross_entity.dart'; +import 'file_system/file_system_cross_directory.dart'; +import 'file_system/file_system_cross_file.dart'; import 'scoped_storage/scoped_storage_cross_directory.dart'; import 'scoped_storage/scoped_storage_cross_file.dart'; @@ -19,6 +21,18 @@ abstract base class XDirectory extends XEntity { @protected const XDirectory(PlatformXDirectory super.platform); + /// Instantiates a [FileSystemXDirectory] as a reference to a directory + /// (or folder) on the file system. + factory XDirectory.fileSystem(String path) { + return FileSystemXDirectory(path); + } + + /// Instantiates a [ScopedStorageXFile] as a reference to a directory + /// (or folder) on the file system within a devices scoped storage. + factory XDirectory.scopedStorage({required String uri}) { + return ScopedStorageXDirectory(uri: uri); + } + /// Implementation of [PlatformXDirectory] for the current platform. @internal @override @@ -33,6 +47,10 @@ abstract base class XDirectory extends XEntity { return ScopedStorageXFile.fromPlatform(entity); case PlatformScopedStorageXDirectory(): return ScopedStorageXDirectory.fromPlatform(entity); + case PlatformFileSystemXFile(): + return FileSystemXFile.fromPlatform(entity); + case PlatformFileSystemXDirectory(): + return FileSystemXDirectory.fromPlatform(entity); } return XEntity(entity); diff --git a/packages/cross_file/cross_file/lib/src/cross_file.dart b/packages/cross_file/cross_file/lib/src/cross_file.dart index f0abbb755e03..229b09a85bb7 100644 --- a/packages/cross_file/cross_file/lib/src/cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/cross_file.dart @@ -9,6 +9,8 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart import 'package:flutter/foundation.dart' show immutable, internal, protected; import 'cross_entity.dart'; +import 'file_system/file_system_cross_file.dart'; +import 'scoped_storage/scoped_storage_cross_file.dart'; /// A reference to a local data resource. @immutable @@ -18,6 +20,18 @@ abstract base class XFile extends XEntity { @protected const XFile(PlatformXFile super.platform); + /// Instantiates a [FileSystemXFile] as a reference to a local data resource + /// on the file system. + factory XFile.fileSystem({required String path}) { + return FileSystemXFile(path); + } + + /// Instantiates a [ScopedStorageXFile] as a reference to a local data + /// resource within a device's scoped storage. + factory XFile.scopedStorage({required String uri}) { + return ScopedStorageXFile(uri: uri); + } + /// Implementation of [XFile] for the current platform. @internal @override From 34dad205199437e85937a1cb020a20ed9c97147d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 13:42:25 -0400 Subject: [PATCH 383/398] set up file system implementation across everything --- .../cross_file/lib/src/cross_directory.dart | 4 +- .../file_system/file_system_cross_file.dart | 13 ++ .../cross_file/test/cross_file_test.dart | 102 ------------- ... => file_system_cross_directory_test.dart} | 19 +-- .../test/file_system_cross_file_test.dart | 135 ++++++++++++++++++ .../scoped_storage_cross_directory_test.dart | 2 +- .../cross_file/test/test_stubs.dart | 49 ++++--- .../cross_file_android/example/lib/main.dart | 2 +- .../lib/cross_file_android.dart | 2 +- ...ndroid_scoped_storage_cross_directory.dart | 2 +- ...d_scoped_storage_cross_directory_test.dart | 2 +- .../cross_file_darwin/example/lib/main.dart | 2 +- .../lib/cross_file_darwin.dart | 2 +- ...darwin_scoped_storage_cross_directory.dart | 2 +- ...n_scoped_storage_cross_directory_test.dart | 2 +- .../cross_file_io/example/lib/main.dart | 2 +- .../cross_file_io/lib/cross_file_io.dart | 2 +- .../src/io_file_system_cross_directory.dart | 2 +- .../lib/src/io_file_system_cross_file.dart | 6 + .../test/io_cross_directory_test.dart | 2 +- .../test/io_cross_file_test.dart | 12 ++ .../lib/src/cross_file_platform.dart | 9 +- .../platform_file_system_cross_file.dart | 16 +++ .../lib/src/platform_cross_directory.dart | 7 +- .../test/cross_file_platform_test.dart | 4 +- .../cross_file_web/lib/cross_file_web.dart | 7 +- 26 files changed, 256 insertions(+), 153 deletions(-) delete mode 100644 packages/cross_file/cross_file/test/cross_file_test.dart rename packages/cross_file/cross_file/test/{cross_directory_test.dart => file_system_cross_directory_test.dart} (63%) create mode 100644 packages/cross_file/cross_file/test/file_system_cross_file_test.dart diff --git a/packages/cross_file/cross_file/lib/src/cross_directory.dart b/packages/cross_file/cross_file/lib/src/cross_directory.dart index f4de1651e50e..43da9e08a9bd 100644 --- a/packages/cross_file/cross_file/lib/src/cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/cross_directory.dart @@ -23,7 +23,7 @@ abstract base class XDirectory extends XEntity { /// Instantiates a [FileSystemXDirectory] as a reference to a directory /// (or folder) on the file system. - factory XDirectory.fileSystem(String path) { + factory XDirectory.fileSystem({required String path}) { return FileSystemXDirectory(path); } @@ -41,7 +41,7 @@ abstract base class XDirectory extends XEntity { /// Lists the sub-directories and files of this directory. Stream list() { // Converts PlatformXEntities to XEntities. - return platform.list(ListParams()).map((PlatformXEntity entity) { + return platform.list(const PlatformListParams()).map((PlatformXEntity entity) { switch (entity) { case PlatformScopedStorageXFile(): return ScopedStorageXFile.fromPlatform(entity); diff --git a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart index e304e4519acc..6ba47fae9c82 100644 --- a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:typed_data'; + import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; import 'package:flutter/foundation.dart' show TargetPlatform, defaultTargetPlatform, immutable, internal; @@ -77,4 +79,15 @@ base class FileSystemXFile extends XFile { @internal @override PlatformFileSystemXFile get platform => super.platform as PlatformFileSystemXFile; + + /// Writes a list of bytes to a file. + /// + /// Platforms may throw an exception if there is an error opening or writing + /// to the file. + Future writeAsBytes(Uint8List bytes) async { + final PlatformFileSystemXFile platformFile = await platform.writeAsBytes( + PlatformWriteAsBytesParams(bytes), + ); + return FileSystemXFile.fromPlatform(platformFile); + } } diff --git a/packages/cross_file/cross_file/test/cross_file_test.dart b/packages/cross_file/cross_file/test/cross_file_test.dart deleted file mode 100644 index d92065310bc7..000000000000 --- a/packages/cross_file/cross_file/test/cross_file_test.dart +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:cross_file/cross_file.dart'; -import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'test_stubs.dart'; - -void main() { - group('XFile', () { - test('lastModified', () async { - final lastModified = DateTime.now(); - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onLastModified: () async => lastModified), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.lastModified(), lastModified); - }); - - test('length', () async { - const length = 42; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onLength: () async => length), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.length(), length); - }); - - test('openRead', () async { - final data = [ - Uint8List.fromList([5, 6]), - ]; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onOpenRead: () => Stream.fromIterable(data)), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.openRead().toList(), data); - }); - - test('readAsBytes', () async { - final bytes = Uint8List.fromList([1, 2, 3]); - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onReadAsBytes: () async => bytes), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.readAsBytes(), bytes); - }); - - test('readAsString', () async { - const message = 'Hello, World!'; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onReadAsString: ({required Encoding encoding}) async => message), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.readAsString(), message); - }); - - test('exists', () async { - const exists = true; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onExists: () async => exists), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.exists(), exists); - }); - - test('name', () async { - const name = 'name'; - CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXFile: (PlatformXFileCreationParams params) => - TestXFile(params, onName: () async => name), - ); - - final file = XFile(uri: 'uri'); - - expect(await file.name(), name); - }); - }); -} diff --git a/packages/cross_file/cross_file/test/cross_directory_test.dart b/packages/cross_file/cross_file/test/file_system_cross_directory_test.dart similarity index 63% rename from packages/cross_file/cross_file/test/cross_directory_test.dart rename to packages/cross_file/cross_file/test/file_system_cross_directory_test.dart index e25ec6da5b2d..e2229540cc28 100644 --- a/packages/cross_file/cross_file/test/cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/file_system_cross_directory_test.dart @@ -13,27 +13,30 @@ void main() { test('exists', () async { const exists = true; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXDirectory: (PlatformXDirectoryCreationParams params) => - TestXDirectory(params, onExists: () async => exists), + onCreatePlatformFileSystemXDirectory: (PlatformFileSystemXDirectoryCreationParams params) => + TestFileSystemXDirectory(params, onExists: () async => exists), ); - final directory = XDirectory(uri: 'uri'); + final directory = XDirectory.fileSystem(path: 'my/dir/'); expect(await directory.exists(), exists); }); test('list', () async { final entities = [ - TestXFile(const PlatformXFileCreationParams(uri: 'uri1')), - TestXDirectory(const PlatformXDirectoryCreationParams(uri: 'uri2')), + TestFileSystemXFile(PlatformFileSystemXFileCreationParams('to/myFile.txt')), + TestFileSystemXDirectory(PlatformFileSystemXDirectoryCreationParams('files/')), TestXEntity(const PlatformXFileCreationParams(uri: 'uri3')), ]; CrossFilePlatform.instance = TestCrossFilePlatform( - onCreatePlatformXDirectory: (PlatformXDirectoryCreationParams params) => - TestXDirectory(params, onList: (ListParams params) => Stream.fromIterable(entities)), + onCreatePlatformFileSystemXDirectory: (PlatformFileSystemXDirectoryCreationParams params) => + TestFileSystemXDirectory( + params, + onList: (PlatformListParams params) => Stream.fromIterable(entities), + ), ); - final directory = XDirectory(uri: 'uri'); + final directory = XDirectory.fileSystem(path: 'my/dir/'); final List directoryEntities = await directory.list().toList(); expect(directoryEntities.length, entities.length); diff --git a/packages/cross_file/cross_file/test/file_system_cross_file_test.dart b/packages/cross_file/cross_file/test/file_system_cross_file_test.dart new file mode 100644 index 000000000000..b0ddb64c23ec --- /dev/null +++ b/packages/cross_file/cross_file/test/file_system_cross_file_test.dart @@ -0,0 +1,135 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cross_file/cross_file.dart'; +import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'test_stubs.dart'; + +void main() { + group('XFile', () { + test('lastModified', () async { + final lastModified = DateTime.now(); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onLastModified: () async => lastModified), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.lastModified(), lastModified); + }); + + test('length', () async { + const length = 42; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onLength: () async => length), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.length(), length); + }); + + test('openRead', () async { + final data = [ + Uint8List.fromList([5, 6]), + ]; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onOpenRead: () => Stream.fromIterable(data)), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.openRead().toList(), data); + }); + + test('readAsBytes', () async { + final bytes = Uint8List.fromList([1, 2, 3]); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onReadAsBytes: () async => bytes), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.readAsBytes(), bytes); + }); + + test('readAsString', () async { + const message = 'Hello, World!'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile( + params, + onReadAsString: ({required Encoding encoding}) async => message, + ), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.readAsString(), message); + }); + + test('exists', () async { + const exists = true; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onExists: () async => exists), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.exists(), exists); + }); + + test('name', () async { + const name = 'name'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onName: () async => name), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.name(), name); + }); + + test('name', () async { + const name = 'name'; + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile(params, onName: () async => name), + ); + + final file = XFile.fileSystem(path: 'to/myFile.txt'); + + expect(await file.name(), name); + }); + + test('writeAsBytes', () async { + final testBytes = Uint8List.fromList([0, 1, 2, 3]); + CrossFilePlatform.instance = TestCrossFilePlatform( + onCreatePlatformFileSystemXFile: (PlatformFileSystemXFileCreationParams params) => + TestFileSystemXFile( + params, + onWriteAsBytes: expectAsync1((Uint8List bytes) async { + expect(bytes, testBytes); + return TestFileSystemXFile(params); + }), + ), + ); + + final file = FileSystemXFile('to/myFile.txt'); + + await file.writeAsBytes(testBytes); + }); + }); +} diff --git a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart index 052bcec032e8..faba4f01ad78 100644 --- a/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file/test/scoped_storage_cross_directory_test.dart @@ -35,7 +35,7 @@ void main() { onCreatePlatformScopedStorageXDirectory: (PlatformScopedStorageXDirectoryCreationParams params) => TestScopedStorageXDirectory( params, - onList: (ListParams params) => Stream.fromIterable(entities), + onList: (PlatformListParams params) => Stream.fromIterable(entities), ), ); diff --git a/packages/cross_file/cross_file/test/test_stubs.dart b/packages/cross_file/cross_file/test/test_stubs.dart index 5d8b1404e461..efd760e38bf4 100644 --- a/packages/cross_file/cross_file/test/test_stubs.dart +++ b/packages/cross_file/cross_file/test/test_stubs.dart @@ -9,15 +9,17 @@ import 'package:cross_file_platform_interface/cross_file_platform_interface.dart final class TestCrossFilePlatform extends CrossFilePlatform { TestCrossFilePlatform({ - this.onCreatePlatformXFile, - this.onCreatePlatformXDirectory, + this.onCreatePlatformFileSystemXFile, + this.onCreatePlatformFileSystemXDirectory, this.onCreatePlatformScopedStorageXFile, this.onCreatePlatformScopedStorageXDirectory, }); - PlatformXFile Function(PlatformXFileCreationParams params)? onCreatePlatformXFile; + PlatformFileSystemXFile Function(PlatformFileSystemXFileCreationParams params)? + onCreatePlatformFileSystemXFile; - PlatformXDirectory Function(PlatformXDirectoryCreationParams params)? onCreatePlatformXDirectory; + PlatformFileSystemXDirectory Function(PlatformFileSystemXDirectoryCreationParams params)? + onCreatePlatformFileSystemXDirectory; PlatformScopedStorageXFile Function(PlatformScopedStorageXFileCreationParams params)? onCreatePlatformScopedStorageXFile; @@ -26,13 +28,17 @@ final class TestCrossFilePlatform extends CrossFilePlatform { onCreatePlatformScopedStorageXDirectory; @override - PlatformXFile createPlatformXFile(PlatformXFileCreationParams params) { - return onCreatePlatformXFile?.call(params) ?? TestXFile(params); + PlatformFileSystemXFile createPlatformFileSystemXFile( + PlatformFileSystemXFileCreationParams params, + ) { + return onCreatePlatformFileSystemXFile?.call(params) ?? TestFileSystemXFile(params); } @override - PlatformXDirectory createPlatformXDirectory(PlatformXDirectoryCreationParams params) { - return onCreatePlatformXDirectory?.call(params) ?? TestXDirectory(params); + PlatformFileSystemXDirectory createPlatformFileSystemXDirectory( + PlatformFileSystemXDirectoryCreationParams params, + ) { + return onCreatePlatformFileSystemXDirectory?.call(params) ?? TestFileSystemXDirectory(params); } @override @@ -51,8 +57,8 @@ final class TestCrossFilePlatform extends CrossFilePlatform { } } -final class TestXFile extends PlatformXFile { - TestXFile( +final class TestFileSystemXFile extends PlatformFileSystemXFile { + TestFileSystemXFile( super.params, { this.onExists, this.onLastModified, @@ -61,6 +67,7 @@ final class TestXFile extends PlatformXFile { this.onOpenRead, this.onReadAsBytes, this.onReadAsString, + this.onWriteAsBytes, }) : super.implementation(); Future Function()? onExists; @@ -70,6 +77,7 @@ final class TestXFile extends PlatformXFile { Stream Function()? onOpenRead; Future Function()? onReadAsBytes; Future Function({required Encoding encoding})? onReadAsString; + Future Function(Uint8List bytes)? onWriteAsBytes; @override Future exists() async { @@ -107,13 +115,22 @@ final class TestXFile extends PlatformXFile { Future readAsString({Encoding encoding = utf8}) async { return await onReadAsString?.call(encoding: encoding) ?? ''; } + + @override + Future writeAsBytes(PlatformWriteAsBytesParams params) async { + if (onWriteAsBytes != null) { + return onWriteAsBytes!.call(params.bytes); + } + + throw UnimplementedError(); + } } -final class TestXDirectory extends PlatformXDirectory { - TestXDirectory(super.params, {this.onExists, this.onList}) : super.implementation(); +final class TestFileSystemXDirectory extends PlatformFileSystemXDirectory { + TestFileSystemXDirectory(super.params, {this.onExists, this.onList}) : super.implementation(); Future Function()? onExists; - Stream Function(ListParams params)? onList; + Stream Function(PlatformListParams params)? onList; @override Future exists() async { @@ -121,7 +138,7 @@ final class TestXDirectory extends PlatformXDirectory { } @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { if (onList != null) { yield* onList!.call(params); } @@ -210,7 +227,7 @@ final class TestScopedStorageXDirectory extends PlatformScopedStorageXDirectory }) : super.implementation(); Future Function()? onExists; - Stream Function(ListParams params)? onList; + Stream Function(PlatformListParams params)? onList; Future Function()? onCanRead; Future Function()? onDispose; @@ -225,7 +242,7 @@ final class TestScopedStorageXDirectory extends PlatformScopedStorageXDirectory } @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { if (onList != null) { yield* onList!.call(params); } diff --git a/packages/cross_file/cross_file_android/example/lib/main.dart b/packages/cross_file/cross_file_android/example/lib/main.dart index 665fd111009e..3df7438e4add 100644 --- a/packages/cross_file/cross_file_android/example/lib/main.dart +++ b/packages/cross_file/cross_file_android/example/lib/main.dart @@ -61,7 +61,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final PlatformXEntity entity in directory.list(ListParams())) { + await for (final PlatformXEntity entity in directory.list(const PlatformListParams())) { switch (entity) { case final PlatformXFile file: final String filename = await file.name() ?? file.params.uri; diff --git a/packages/cross_file/cross_file_android/lib/cross_file_android.dart b/packages/cross_file/cross_file_android/lib/cross_file_android.dart index e579dc00edb0..e974aeb591c1 100644 --- a/packages/cross_file/cross_file_android/lib/cross_file_android.dart +++ b/packages/cross_file/cross_file_android/lib/cross_file_android.dart @@ -4,7 +4,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - ListParams, + PlatformListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, PlatformXDirectoryCreationParams, diff --git a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart index 63076235b3d4..1a15128223c0 100644 --- a/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_android/lib/src/android_scoped_storage_cross_directory.dart @@ -23,7 +23,7 @@ base class AndroidScopedStorageXDirectory extends PlatformScopedStorageXDirector } @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { for (final DocumentFile documentFile in await _documentFile.listFiles()) { final String uri = await documentFile.getUri(); if (await documentFile.isFile()) { diff --git a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart index ea92c4d51763..0976e35cb119 100644 --- a/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_android/test/android_scoped_storage_cross_directory_test.dart @@ -81,7 +81,7 @@ void main() { ); final List entityUris = await dir - .list(ListParams()) + .list(const PlatformListParams()) .map((PlatformXEntity entity) => entity.params.uri) .toList(); diff --git a/packages/cross_file/cross_file_darwin/example/lib/main.dart b/packages/cross_file/cross_file_darwin/example/lib/main.dart index 665fd111009e..3df7438e4add 100644 --- a/packages/cross_file/cross_file_darwin/example/lib/main.dart +++ b/packages/cross_file/cross_file_darwin/example/lib/main.dart @@ -61,7 +61,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final PlatformXEntity entity in directory.list(ListParams())) { + await for (final PlatformXEntity entity in directory.list(const PlatformListParams())) { switch (entity) { case final PlatformXFile file: final String filename = await file.name() ?? file.params.uri; diff --git a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart index de7151eb129b..eccda055887f 100644 --- a/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart +++ b/packages/cross_file/cross_file_darwin/lib/cross_file_darwin.dart @@ -4,7 +4,7 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - ListParams, + PlatformListParams, PlatformScopedStorageXDirectoryCreationParams, PlatformScopedStorageXFileCreationParams, PlatformXDirectoryCreationParams, diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart index e94bbb10b805..4b3325ed524a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_directory.dart @@ -79,7 +79,7 @@ base class SecurityScopedDarwinScopedStorageXDirectory extends DarwinScopedStora Future exists() async => _directory.existsSync(); @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { await for (final FileSystemEntity entity in _directory.list()) { switch (entity) { case final Directory directory: diff --git a/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart b/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart index 1b738b609eab..cf21568f0969 100644 --- a/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart +++ b/packages/cross_file/cross_file_darwin/test/security_scoped_darwin_scoped_storage_cross_directory_test.dart @@ -30,7 +30,7 @@ void main() { ); expect( - (await directory.list(ListParams()).toList()).map( + (await directory.list(const PlatformListParams()).toList()).map( (PlatformXEntity entity) => entity.params.uri, ), (await testDirectory.list().toList()).map((FileSystemEntity entity) => entity.uri.toString()), diff --git a/packages/cross_file/cross_file_io/example/lib/main.dart b/packages/cross_file/cross_file_io/example/lib/main.dart index 665fd111009e..3df7438e4add 100644 --- a/packages/cross_file/cross_file_io/example/lib/main.dart +++ b/packages/cross_file/cross_file_io/example/lib/main.dart @@ -61,7 +61,7 @@ class FileOpenScreen extends StatelessWidget { debugPrint('Directory exists: ${await directory.exists()}'); debugPrint('List of Entities:'); - await for (final PlatformXEntity entity in directory.list(ListParams())) { + await for (final PlatformXEntity entity in directory.list(const PlatformListParams())) { switch (entity) { case final PlatformXFile file: final String filename = await file.name() ?? file.params.uri; diff --git a/packages/cross_file/cross_file_io/lib/cross_file_io.dart b/packages/cross_file/cross_file_io/lib/cross_file_io.dart index dc3b99cc9c8d..049fbc95d3c5 100644 --- a/packages/cross_file/cross_file_io/lib/cross_file_io.dart +++ b/packages/cross_file/cross_file_io/lib/cross_file_io.dart @@ -4,9 +4,9 @@ export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' show - ListParams, PlatformFileSystemXDirectoryCreationParams, PlatformFileSystemXFileCreationParams, + PlatformListParams, PlatformXDirectoryCreationParams, PlatformXFileCreationParams; diff --git a/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart index 33a2f43d2d1a..63d7084b38cc 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_directory.dart @@ -52,7 +52,7 @@ base class IOFileSystemXDirectory extends PlatformFileSystemXDirectory Future exists() async => directory.existsSync(); @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { await for (final FileSystemEntity entity in directory.list()) { switch (entity) { case final Directory directory: diff --git a/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart index 2bfc95b04b05..6b12bcf5a00f 100644 --- a/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart +++ b/packages/cross_file/cross_file_io/lib/src/io_file_system_cross_file.dart @@ -79,6 +79,12 @@ base class IOFileSystemXFile extends PlatformFileSystemXFile with IOFileSystemXF @override Future name() async => path.basename(file.path); + + @override + Future writeAsBytes(PlatformWriteAsBytesParams params) async { + final File ioFile = await file.writeAsBytes(params.bytes); + return IOFileSystemXFile(IOFileSystemXFileCreationParams.fromFile(ioFile)); + } } /// Provides platform-specific features for [IOFileSystemXFile]. diff --git a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart index 9fde0b3a0aa4..2340a57bc90c 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_directory_test.dart @@ -31,7 +31,7 @@ void main() { ); expect( - (await directory.list(ListParams()).toList()).map( + (await directory.list(const PlatformListParams()).toList()).map( (PlatformXEntity entity) => entity.params.uri, ), (await testDirectory.list().toList()).map( diff --git a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart index f4f0114c5bf4..db5480283092 100644 --- a/packages/cross_file/cross_file_io/test/io_cross_file_test.dart +++ b/packages/cross_file/cross_file_io/test/io_cross_file_test.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. import 'dart:io'; +import 'dart:typed_data'; import 'package:cross_file_io/cross_file_io.dart'; import 'package:cross_file_platform_interface/cross_file_platform_interface.dart'; @@ -58,5 +59,16 @@ void main() { expect(await file.name(), 'test_file.txt'); }); + + test('writeAsBytes', () async { + final Directory tempDir = Directory.systemTemp; + final tempFile = File(path.join(tempDir.path, 'test_file.txt')); + + final bytes = Uint8List.fromList([0, 1, 2, 3]); + final file = PlatformFileSystemXFile(PlatformFileSystemXFileCreationParams(tempFile.path)); + await file.writeAsBytes(PlatformWriteAsBytesParams(bytes)); + + expect(await file.readAsBytes(), bytes); + }); }); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart index e5f234c9db26..8500c179626e 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/cross_file_platform.dart @@ -81,6 +81,11 @@ final class _DefaultFileSystemXFile extends PlatformFileSystemXFile { Future readAsString({Encoding encoding = utf8}) { throw UnsupportedError('This instance does not represent any resource.'); } + + @override + Future writeAsBytes(PlatformWriteAsBytesParams params) { + throw UnsupportedError('This instance does not represent any resource.'); + } } /// Implementation of [PlatformFileSystemXDirectory} that represents a directory @@ -92,7 +97,7 @@ final class _DefaultFileSystemXDirectory extends PlatformFileSystemXDirectory { Future exists() async => false; @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { throw UnsupportedError('This instance does not represent any directory.'); } } @@ -148,7 +153,7 @@ final class _DefaultScopedStorageXDirectory extends PlatformScopedStorageXDirect Future canRead() async => false; @override - Stream list(ListParams params) async* { + Stream list(PlatformListParams params) async* { throw UnsupportedError('This instance does not represent any directory.'); } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart index 54685a800822..07432a08a5aa 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/file_system/platform_file_system_cross_file.dart @@ -95,4 +95,20 @@ abstract base class PlatformFileSystemXFile extends PlatformXFile { @override PlatformFileSystemXFileCreationParams get params => super.params as PlatformFileSystemXFileCreationParams; + + /// Writes a list of bytes to a file. + /// + /// Platforms may throw an exception if there is an error opening or writing + /// to the file. + Future writeAsBytes(PlatformWriteAsBytesParams params); +} + +/// Base class for parameters passed to [PlatformFileSystemXFile.writeAsBytes]. +@immutable +base class PlatformWriteAsBytesParams { + /// Constructs a [PlatformWriteAsBytesParams]. + const PlatformWriteAsBytesParams(this.bytes); + + /// List of bytes to write to the file. + final Uint8List bytes; } diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 64fade77d0b3..6883b6fc4840 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -82,9 +82,12 @@ abstract base class PlatformXDirectory extends PlatformXEntity { /// /// Platforms may throw an exception if there is an error listing entities in /// the directory - Stream list(ListParams params); + Stream list(PlatformListParams params); } /// Base class for parameters passed to [PlatformXDirectory.list]. @immutable -base class ListParams {} +base class PlatformListParams { + /// Constructs a [PlatformListParams]; + const PlatformListParams(); +} diff --git a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart index 52d284532729..6bf6ac8bb66e 100644 --- a/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart +++ b/packages/cross_file/cross_file_platform_interface/test/cross_file_platform_test.dart @@ -51,7 +51,7 @@ void main() { ); // Ensures the error is caught and added to the stream. - await expectLater(dir.list(ListParams()).drain, throwsUnsupportedError); + await expectLater(dir.list(const PlatformListParams()).drain, throwsUnsupportedError); }); }); @@ -107,7 +107,7 @@ void main() { ); // Ensures the error is caught and added to the stream. - await expectLater(dir.list(ListParams()).drain, throwsUnsupportedError); + await expectLater(dir.list(const PlatformListParams()).drain, throwsUnsupportedError); }, ); }); diff --git a/packages/cross_file/cross_file_web/lib/cross_file_web.dart b/packages/cross_file/cross_file_web/lib/cross_file_web.dart index f10bf4927edf..282074e05fab 100644 --- a/packages/cross_file/cross_file_web/lib/cross_file_web.dart +++ b/packages/cross_file/cross_file_web/lib/cross_file_web.dart @@ -3,12 +3,7 @@ // found in the LICENSE file. export 'package:cross_file_platform_interface/cross_file_platform_interface.dart' - show - ListParams, - PlatformScopedStorageXDirectoryCreationParams, - PlatformScopedStorageXFileCreationParams, - PlatformXDirectoryCreationParams, - PlatformXFileCreationParams; + show PlatformScopedStorageXFileCreationParams, PlatformXFileCreationParams; export 'src/cross_file_web.dart'; export 'src/web_scoped_storage_cross_file.dart' From f8a820438106e58e2e0377933032d9559eda0945 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 19:27:46 -0400 Subject: [PATCH 384/398] formatting --- .../AssetResourceReader.swift | 40 ++- .../AssetResourceReaderDelegate.swift | 25 +- .../CrossFileDarwinApis.g.swift | 271 ++++++++++++------ .../CrossFileDarwinPlugin.swift | 24 +- .../cross_file_darwin/ProxyAPIRegistrar.swift | 11 +- .../lib/src/cross_file_darwin_apis.g.dart | 270 ++++++++--------- 6 files changed, 359 insertions(+), 282 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift index aad7ef8ebf49..327fef1e9590 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReader.swift @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import Photos import Foundation +import Photos /// Class for handling an instance of asynchronously reading bytes from an asset. class AssetResourceReader { @@ -40,21 +40,31 @@ class AssetResourceReader { /// Read all bytes from asset with identifier. func readBytes(localIdentifier: String, completion: @escaping (Result) -> Void) { - let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) - if let asset = assets.firstObject { - let manager = PHImageManager.default() - let options = PHImageRequestOptions() - options.isNetworkAccessAllowed = true - manager.requestImageDataAndOrientation(for: asset, options: options) { (data, _, _, _) in - if (data != nil) { - completion(.success(data!)) - } else { - completion(.failure(PigeonError(code: "XFileNullDataError", message: "Failed to read byes from asset with identifier: \(localIdentifier)", details: nil))) - } - } - } else { - completion(.failure(PigeonError(code: "XFileMissingAssetError", message: "Failed to read byes from asset with identifier: \(localIdentifier)", details: nil))) + let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: nil) + if let asset = assets.firstObject { + let manager = PHImageManager.default() + let options = PHImageRequestOptions() + options.isNetworkAccessAllowed = true + manager.requestImageDataAndOrientation(for: asset, options: options) { (data, _, _, _) in + if data != nil { + completion(.success(data!)) + } else { + completion( + .failure( + PigeonError( + code: "XFileNullDataError", + message: "Failed to read bytes from asset with identifier: \(localIdentifier)", + details: nil))) + } } + } else { + completion( + .failure( + PigeonError( + code: "XFileMissingAssetError", + message: "Failed to find asset with identifier: \(localIdentifier)", + details: nil))) + } } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReaderDelegate.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReaderDelegate.swift index 4fc10cb14820..2f24c0aab17c 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReaderDelegate.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/AssetResourceReaderDelegate.swift @@ -26,16 +26,19 @@ class AssetResourceReaderAPIDelegate: PigeonApiDelegateAssetResourceReader { ) throws -> Bool { return pigeonInstance.openRead(localIdentifier: localIdentifier, delegate: delegate) } - - func readBytes(pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, localIdentifier: String, completion: @escaping (Result) -> Void) { - pigeonInstance.readBytes(localIdentifier: localIdentifier) { result in - switch(result) { - case .failure(let error): - completion(.failure(error)) - case .success(let bytes): - completion(.success(FlutterStandardTypedData(bytes: bytes))) - } - } - + + func readBytes( + pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, + localIdentifier: String, completion: @escaping (Result) -> Void + ) { + pigeonInstance.readBytes(localIdentifier: localIdentifier) { result in + switch result { + case .failure(let error): + completion(.failure(error)) + case .success(let bytes): + completion(.success(FlutterStandardTypedData(bytes: bytes))) + } } + + } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift index 35a1a9bc4782..71ac379e9ba0 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinApis.g.swift @@ -59,7 +59,9 @@ private func wrapError(_ error: Any) -> [Any?] { } private func createConnectionError(withChannelName channelName: String) -> PigeonError { - return PigeonError(code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", details: "") + return PigeonError( + code: "channel-error", message: "Unable to establish connection on channel: '\(channelName)'.", + details: "") } enum CrossFileDarwinApisPigeonInternal { @@ -87,7 +89,6 @@ protocol CrossFileDarwinApisPigeonInternalFinalizerDelegate: AnyObject { func onDeinit(identifier: Int64) } - // Attaches to an object to receive a callback when the object is deallocated. internal final class CrossFileDarwinApisPigeonInternalFinalizer { internal static let associatedObjectKey = malloc(1)! @@ -103,14 +104,18 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } internal static func attach( - to instance: AnyObject, identifier: Int64, delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate + to instance: AnyObject, identifier: Int64, + delegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate ) { - let finalizer = CrossFileDarwinApisPigeonInternalFinalizer(identifier: identifier, delegate: delegate) + let finalizer = CrossFileDarwinApisPigeonInternalFinalizer( + identifier: identifier, delegate: delegate) objc_setAssociatedObject(instance, associatedObjectKey, finalizer, .OBJC_ASSOCIATION_RETAIN) } static func detach(from instance: AnyObject) { - let finalizer = objc_getAssociatedObject(instance, associatedObjectKey) as? CrossFileDarwinApisPigeonInternalFinalizer + let finalizer = + objc_getAssociatedObject(instance, associatedObjectKey) + as? CrossFileDarwinApisPigeonInternalFinalizer if let finalizer = finalizer { finalizer.delegate = nil objc_setAssociatedObject(instance, associatedObjectKey, nil, .OBJC_ASSOCIATION_ASSIGN) @@ -122,7 +127,6 @@ internal final class CrossFileDarwinApisPigeonInternalFinalizer { } } - /// Maintains instances used to communicate with the corresponding objects in Dart. /// /// Objects stored in this container are represented by an object in Dart that is also stored in @@ -226,7 +230,8 @@ final class CrossFileDarwinApisPigeonInstanceManager { identifiers.setObject(NSNumber(value: identifier), forKey: instance) weakInstances.setObject(instance, forKey: NSNumber(value: identifier)) strongInstances.setObject(instance, forKey: NSNumber(value: identifier)) - CrossFileDarwinApisPigeonInternalFinalizer.attach(to: instance, identifier: identifier, delegate: finalizerDelegate) + CrossFileDarwinApisPigeonInternalFinalizer.attach( + to: instance, identifier: identifier, delegate: finalizerDelegate) } /// Retrieves the identifier paired with an instance. @@ -307,7 +312,6 @@ final class CrossFileDarwinApisPigeonInstanceManager { } } - private class CrossFileDarwinApisPigeonInstanceManagerApi { /// The codec used for serializing messages. var codec: FlutterStandardMessageCodec { CrossFileDarwinApisPigeonCodec.shared } @@ -320,9 +324,15 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sets up an instance of `CrossFileDarwinApisPigeonInstanceManagerApi` to handle messages through the `binaryMessenger`. - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, instanceManager: CrossFileDarwinApisPigeonInstanceManager?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, + instanceManager: CrossFileDarwinApisPigeonInstanceManager? + ) { let codec = CrossFileDarwinApisPigeonCodec.shared - let removeStrongReferenceChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", binaryMessenger: binaryMessenger, codec: codec) + let removeStrongReferenceChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { removeStrongReferenceChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -337,7 +347,9 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } else { removeStrongReferenceChannel.setMessageHandler(nil) } - let clearChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", binaryMessenger: binaryMessenger, codec: codec) + let clearChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.clear", + binaryMessenger: binaryMessenger, codec: codec) if let instanceManager = instanceManager { clearChannel.setMessageHandler { _, reply in do { @@ -353,9 +365,13 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { } /// Sends a message to the Dart `InstanceManager` to remove the strong reference of the instance associated with `identifier`. - func removeStrongReference(identifier identifierArg: Int64, completion: @escaping (Result) -> Void) { - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + func removeStrongReference( + identifier identifierArg: Int64, completion: @escaping (Result) -> Void + ) { + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([identifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -375,10 +391,12 @@ private class CrossFileDarwinApisPigeonInstanceManagerApi { protocol CrossFileDarwinApisPigeonProxyApiDelegate { /// An implementation of [PigeonApiAssetResourceReader] used to add a new Dart instance of /// `AssetResourceReader` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceReader + func pigeonApiAssetResourceReader(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiAssetResourceReader /// An implementation of [PigeonApiAssetResourceReaderDelegate] used to add a new Dart instance of /// `AssetResourceReaderDelegate` to the Dart `InstanceManager` and make calls to Dart. - func pigeonApiAssetResourceReaderDelegate(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceReaderDelegate + func pigeonApiAssetResourceReaderDelegate(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiAssetResourceReaderDelegate } open class CrossFileDarwinApisPigeonProxyApiRegistrar { @@ -391,12 +409,15 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { var codec: FlutterStandardMessageCodec { if _codec == nil { _codec = FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: self)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: self)) } return _codec! } - private class InstanceManagerApiFinalizerDelegate: CrossFileDarwinApisPigeonInternalFinalizerDelegate { + private class InstanceManagerApiFinalizerDelegate: + CrossFileDarwinApisPigeonInternalFinalizerDelegate + { let api: CrossFileDarwinApisPigeonInstanceManagerApi init(_ api: CrossFileDarwinApisPigeonInstanceManagerApi) { @@ -410,7 +431,9 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } } - init(binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate) { + init( + binaryMessenger: FlutterBinaryMessenger, apiDelegate: CrossFileDarwinApisPigeonProxyApiDelegate + ) { self.binaryMessenger = binaryMessenger self.apiDelegate = apiDelegate self.instanceManager = CrossFileDarwinApisPigeonInstanceManager( @@ -419,20 +442,29 @@ open class CrossFileDarwinApisPigeonProxyApiRegistrar { } func setUp() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: instanceManager) - PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) - PigeonApiAssetResourceReaderDelegate.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReaderDelegate(self)) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: instanceManager) + PigeonApiAssetResourceReader.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReader(self)) + PigeonApiAssetResourceReaderDelegate.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiAssetResourceReaderDelegate(self)) } func tearDown() { - CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger: binaryMessenger, instanceManager: nil) + CrossFileDarwinApisPigeonInstanceManagerApi.setUpMessageHandlers( + binaryMessenger: binaryMessenger, instanceManager: nil) PigeonApiAssetResourceReader.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) - PigeonApiAssetResourceReaderDelegate.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiAssetResourceReaderDelegate.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: nil) } } -private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { +private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: + FlutterStandardReaderWriter +{ unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar - private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: CrossFileDarwinApisPigeonCodecReader { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecReader: + CrossFileDarwinApisPigeonCodecReader + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: Data, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -456,7 +488,9 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } } - private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: CrossFileDarwinApisPigeonCodecWriter { + private class CrossFileDarwinApisPigeonInternalProxyApiCodecWriter: + CrossFileDarwinApisPigeonCodecWriter + { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar init(data: NSMutableData, pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar) { @@ -465,35 +499,38 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func writeValue(_ value: Any) { - if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String { + if value is [Any] || value is Bool || value is Data || value is [AnyHashable: Any] + || value is Double || value is FlutterStandardTypedData || value is Int64 || value is String + { super.writeValue(value) return } - if let instance = value as? AssetResourceReader { pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReader(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - if let instance = value as? AssetResourceReaderDelegate { - pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReaderDelegate(pigeonRegistrar).pigeonNewInstance( - pigeonInstance: instance - ) { _ in } + pigeonRegistrar.apiDelegate.pigeonApiAssetResourceReaderDelegate(pigeonRegistrar) + .pigeonNewInstance( + pigeonInstance: instance + ) { _ in } super.writeByte(128) super.writeValue( - pigeonRegistrar.instanceManager.identifierWithStrongReference(forInstance: instance as AnyObject)!) + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) return } - - if let instance = value as AnyObject?, pigeonRegistrar.instanceManager.containsInstance(instance) + if let instance = value as AnyObject?, + pigeonRegistrar.instanceManager.containsInstance(instance) { super.writeByte(128) super.writeValue( @@ -511,11 +548,13 @@ private class CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter: Flutte } override func reader(with data: Data) -> FlutterStandardReader { - return CrossFileDarwinApisPigeonInternalProxyApiCodecReader(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecReader( + data: data, pigeonRegistrar: pigeonRegistrar) } override func writer(with data: NSMutableData) -> FlutterStandardWriter { - return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter(data: data, pigeonRegistrar: pigeonRegistrar) + return CrossFileDarwinApisPigeonInternalProxyApiCodecWriter( + data: data, pigeonRegistrar: pigeonRegistrar) } } @@ -536,12 +575,14 @@ private class CrossFileDarwinApisPigeonCodecReaderWriter: FlutterStandardReaderW } class CrossFileDarwinApisPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable { - static let shared = CrossFileDarwinApisPigeonCodec(readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) + static let shared = CrossFileDarwinApisPigeonCodec( + readerWriter: CrossFileDarwinApisPigeonCodecReaderWriter()) } protocol PigeonApiDelegateAssetResourceReader { /// Constructs a [AssetResourceReader]. - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws -> AssetResourceReader + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReader) throws + -> AssetResourceReader /// Start reading bytes from the asset with the given identifier. /// /// Returns false if the resource for the identifier could not be accessed or @@ -551,38 +592,52 @@ protocol PigeonApiDelegateAssetResourceReader { /// `onCompletion` is called. /// /// See [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). - func openRead(pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, localIdentifier: String, delegate: AssetResourceReaderDelegate) throws -> Bool + func openRead( + pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, + localIdentifier: String, delegate: AssetResourceReaderDelegate + ) throws -> Bool /// Reads the entire asset contents as a list of bytes. /// /// See [AssetResourceReader.requestImageDataAndOrientationForAsset](https://developer.apple.com/documentation/photos/phimagemanager/requestimagedataandorientation(for:options:resulthandler:)?changes=_6_4_2). - func readBytes(pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, localIdentifier: String, completion: @escaping (Result) -> Void) + func readBytes( + pigeonApi: PigeonApiAssetResourceReader, pigeonInstance: AssetResourceReader, + localIdentifier: String, completion: @escaping (Result) -> Void + ) } protocol PigeonApiProtocolAssetResourceReader { } -final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { +final class PigeonApiAssetResourceReader: PigeonApiProtocolAssetResourceReader { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateAssetResourceReader - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateAssetResourceReader) { + init( + pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateAssetResourceReader + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReader? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", binaryMessenger: binaryMessenger, codec: codec) + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { pigeonDefaultConstructorChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( -try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), -withIdentifier: pigeonIdentifierArg) + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -591,7 +646,9 @@ withIdentifier: pigeonIdentifierArg) } else { pigeonDefaultConstructorChannel.setMessageHandler(nil) } - let openReadChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead", binaryMessenger: binaryMessenger, codec: codec) + let openReadChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { openReadChannel.setMessageHandler { message, reply in let args = message as! [Any?] @@ -599,7 +656,9 @@ withIdentifier: pigeonIdentifierArg) let localIdentifierArg = args[1] as! String let delegateArg = args[2] as! AssetResourceReaderDelegate do { - let result = try api.pigeonDelegate.openRead(pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg, delegate: delegateArg) + let result = try api.pigeonDelegate.openRead( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg, + delegate: delegateArg) reply(wrapResult(result)) } catch { reply(wrapError(error)) @@ -608,13 +667,17 @@ withIdentifier: pigeonIdentifierArg) } else { openReadChannel.setMessageHandler(nil) } - let readBytesChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.readBytes", binaryMessenger: binaryMessenger, codec: codec) + let readBytesChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.readBytes", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { readBytesChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! AssetResourceReader let localIdentifierArg = args[1] as! String - api.pigeonDelegate.readBytes(pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg) { result in + api.pigeonDelegate.readBytes( + pigeonApi: api, pigeonInstance: pigeonInstanceArg, localIdentifier: localIdentifierArg + ) { result in switch result { case .success(let res): reply(wrapResult(res)) @@ -629,21 +692,26 @@ withIdentifier: pigeonIdentifierArg) } ///Creates a Dart instance of AssetResourceReader and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: AssetResourceReader, completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { - let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeonInstance as AnyObject) + } else { + let pigeonIdentifierArg = pigeonRegistrar.instanceManager.addHostCreatedInstance( + pigeonInstance as AnyObject) let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_newInstance" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_newInstance" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonIdentifierArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -663,7 +731,8 @@ withIdentifier: pigeonIdentifierArg) } protocol PigeonApiDelegateAssetResourceReaderDelegate { /// Constructs a `ByteHandler`. - func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReaderDelegate) throws -> AssetResourceReaderDelegate + func pigeonDefaultConstructor(pigeonApi: PigeonApiAssetResourceReaderDelegate) throws + -> AssetResourceReaderDelegate } protocol PigeonApiProtocolAssetResourceReaderDelegate { @@ -673,38 +742,52 @@ protocol PigeonApiProtocolAssetResourceReaderDelegate { /// /// Corresponds to the `dataReceivedHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) + func onDataReceived( + pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, + bytes bytesArg: FlutterStandardTypedData, + completion: @escaping (Result) -> Void) /// Indicates the request for data has completed. /// /// Called once after the request has been fulfilled or has failed. /// /// Corresponds to the `completionHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, error errorArg: String?, completion: @escaping (Result) -> Void) + func onCompletion( + pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, error errorArg: String?, + completion: @escaping (Result) -> Void) } -final class PigeonApiAssetResourceReaderDelegate: PigeonApiProtocolAssetResourceReaderDelegate { +final class PigeonApiAssetResourceReaderDelegate: PigeonApiProtocolAssetResourceReaderDelegate { unowned let pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar let pigeonDelegate: PigeonApiDelegateAssetResourceReaderDelegate - init(pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, delegate: PigeonApiDelegateAssetResourceReaderDelegate) { + init( + pigeonRegistrar: CrossFileDarwinApisPigeonProxyApiRegistrar, + delegate: PigeonApiDelegateAssetResourceReaderDelegate + ) { self.pigeonRegistrar = pigeonRegistrar self.pigeonDelegate = delegate } - static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReaderDelegate?) { + static func setUpMessageHandlers( + binaryMessenger: FlutterBinaryMessenger, api: PigeonApiAssetResourceReaderDelegate? + ) { let codec: FlutterStandardMessageCodec = api != nil ? FlutterStandardMessageCodec( - readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter(pigeonRegistrar: api!.pigeonRegistrar)) + readerWriter: CrossFileDarwinApisPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) : FlutterStandardMessageCodec.sharedInstance() - let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.pigeon_defaultConstructor", binaryMessenger: binaryMessenger, codec: codec) + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.pigeon_defaultConstructor", + binaryMessenger: binaryMessenger, codec: codec) if let api = api { pigeonDefaultConstructorChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonIdentifierArg = args[0] as! Int64 do { api.pigeonRegistrar.instanceManager.addDartCreatedInstance( -try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), -withIdentifier: pigeonIdentifierArg) + try api.pigeonDelegate.pigeonDefaultConstructor(pigeonApi: api), + withIdentifier: pigeonIdentifierArg) reply(wrapResult(nil)) } catch { reply(wrapError(error)) @@ -716,21 +799,26 @@ withIdentifier: pigeonIdentifierArg) } ///Creates a Dart instance of AssetResourceReaderDelegate and attaches it to [pigeonInstance]. - func pigeonNewInstance(pigeonInstance: AssetResourceReaderDelegate, completion: @escaping (Result) -> Void) { + func pigeonNewInstance( + pigeonInstance: AssetResourceReaderDelegate, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( PigeonError( code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) - } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { + } else if pigeonRegistrar.instanceManager.containsInstance(pigeonInstance as AnyObject) { completion(.success(())) - } else { + } else { completion( .failure( PigeonError( code: "new-instance-error", - message: "Error: Attempting to create a new Dart instance of AssetResourceReaderDelegate, but the class has a nonnull callback method.", details: ""))) + message: + "Error: Attempting to create a new Dart instance of AssetResourceReaderDelegate, but the class has a nonnull callback method.", + details: ""))) } } /// Provides the requested data. @@ -739,7 +827,11 @@ withIdentifier: pigeonIdentifierArg) /// /// Corresponds to the `dataReceivedHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onDataReceived(pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, bytes bytesArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { + func onDataReceived( + pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, + bytes bytesArg: FlutterStandardTypedData, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -747,18 +839,22 @@ withIdentifier: pigeonIdentifierArg) code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: "Callback to `AssetResourceReaderDelegate.onDataReceived` failed because native instance was not in the instance manager.", details: ""))) + message: + "Callback to `AssetResourceReaderDelegate.onDataReceived` failed because native instance was not in the instance manager.", + details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onDataReceived" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onDataReceived" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, bytesArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) @@ -781,7 +877,10 @@ withIdentifier: pigeonIdentifierArg) /// /// Corresponds to the `completionHandler` parameter for /// `PHAssetResourceManager.requestDataForAssetResource`. - func onCompletion(pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, error errorArg: String?, completion: @escaping (Result) -> Void) { + func onCompletion( + pigeonInstance pigeonInstanceArg: AssetResourceReaderDelegate, error errorArg: String?, + completion: @escaping (Result) -> Void + ) { if pigeonRegistrar.ignoreCallsToDart { completion( .failure( @@ -789,18 +888,22 @@ withIdentifier: pigeonIdentifierArg) code: "ignore-calls-error", message: "Calls to Dart are being ignored.", details: ""))) return - } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { + } else if !pigeonRegistrar.instanceManager.containsInstance(pigeonInstanceArg as AnyObject) { completion( .failure( PigeonError( code: "missing-instance-error", - message: "Callback to `AssetResourceReaderDelegate.onCompletion` failed because native instance was not in the instance manager.", details: ""))) + message: + "Callback to `AssetResourceReaderDelegate.onCompletion` failed because native instance was not in the instance manager.", + details: ""))) return } let binaryMessenger = pigeonRegistrar.binaryMessenger let codec = pigeonRegistrar.codec - let channelName: String = "dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onCompletion" - let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger, codec: codec) + let channelName: String = + "dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onCompletion" + let channel = FlutterBasicMessageChannel( + name: channelName, binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([pigeonInstanceArg, errorArg] as [Any?]) { response in guard let listResponse = response as? [Any?] else { completion(.failure(createConnectionError(withChannelName: channelName))) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift index d278c9f7e125..5f7b07875ebe 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/CrossFileDarwinPlugin.swift @@ -18,21 +18,21 @@ public class CrossFileDarwinPlugin: NSObject, FlutterPlugin { } public static func register(with registrar: FlutterPluginRegistrar) { - #if os(iOS) - let messenger = registrar.messenger() - #elseif os(macOS) - let messenger = registrar.messenger - #endif + #if os(iOS) + let messenger = registrar.messenger() + #elseif os(macOS) + let messenger = registrar.messenger + #endif - let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger) + let plugin = CrossFileDarwinPlugin(binaryMessenger: messenger) - registrar.publish(plugin) + registrar.publish(plugin) } public func detachFromEngine(for registrar: FlutterPluginRegistrar) { - proxyApiRegistrar?.ignoreCallsToDart = true - proxyApiRegistrar?.tearDown() - try? proxyApiRegistrar?.instanceManager.removeAllObjects() - proxyApiRegistrar = nil - } + proxyApiRegistrar?.ignoreCallsToDart = true + proxyApiRegistrar?.tearDown() + try? proxyApiRegistrar?.instanceManager.removeAllObjects() + proxyApiRegistrar = nil + } } diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift index 656cab3c6566..45f1c67ba24f 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin/ProxyAPIRegistrar.swift @@ -52,8 +52,11 @@ class ProxyAPIDelegate: CrossFileDarwinApisPigeonProxyApiDelegate { return PigeonApiAssetResourceReader( pigeonRegistrar: registrar, delegate: AssetResourceReaderAPIDelegate()) } - - func pigeonApiAssetResourceReaderDelegate(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) -> PigeonApiAssetResourceReaderDelegate { - return PigeonApiAssetResourceReaderDelegate(pigeonRegistrar: registrar, delegate: AssetResourceReaderDelegateAPIDelegate()) - } + + func pigeonApiAssetResourceReaderDelegate(_ registrar: CrossFileDarwinApisPigeonProxyApiRegistrar) + -> PigeonApiAssetResourceReaderDelegate + { + return PigeonApiAssetResourceReaderDelegate( + pigeonRegistrar: registrar, delegate: AssetResourceReaderDelegateAPIDelegate()) + } } diff --git a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart index 03f0c9e13baa..d5cb8df3f733 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/cross_file_darwin_apis.g.dart @@ -15,9 +15,9 @@ import 'package:flutter/widgets.dart' show WidgetsFlutterBinding; import 'package:meta/meta.dart' show immutable, protected, visibleForTesting; Object? _extractReplyValueOrThrow( - List? replyList, - String channelName, { - required bool isNullValid, + List? replyList, + String channelName, { + required bool isNullValid, }) { if (replyList == null) { throw PlatformException( @@ -39,7 +39,6 @@ Object? _extractReplyValueOrThrow( return replyList.firstOrNull; } - List wrapResponse({Object? result, PlatformException? error, bool empty = false}) { if (empty) { return []; @@ -49,6 +48,7 @@ List wrapResponse({Object? result, PlatformException? error, bool empty } return [error.code, error.message, error.details]; } + /// Provides overrides for the constructors and static members of each /// Dart proxy class. /// @@ -63,15 +63,11 @@ class PigeonOverrides { /// Overrides [AssetResourceReaderDelegate.new]. static AssetResourceReaderDelegate Function({ - required void Function( - AssetResourceReaderDelegate pigeon_instance, - Uint8List bytes, - ) onDataReceived, - required void Function( - AssetResourceReaderDelegate pigeon_instance, - String? error, - ) onCompletion, - })? assetResourceReaderDelegate_new; + required void Function(AssetResourceReaderDelegate pigeon_instance, Uint8List bytes) + onDataReceived, + required void Function(AssetResourceReaderDelegate pigeon_instance, String? error) onCompletion, + })? + assetResourceReaderDelegate_new; /// Sets all overridden ProxyApi class members to null. static void pigeon_reset() { @@ -91,8 +87,7 @@ abstract class PigeonInternalProxyApiBaseClass { PigeonInternalProxyApiBaseClass({ this.pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInstanceManager.instance; + }) : pigeon_instanceManager = pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -164,7 +159,8 @@ class PigeonInstanceManager { final Expando _identifiers = Expando(); final Map> _weakInstances = >{}; - final Map _strongInstances = {}; + final Map _strongInstances = + {}; late final Finalizer _finalizer; int _nextIdentifier = 0; @@ -187,7 +183,9 @@ class PigeonInstanceManager { ); _PigeonInternalInstanceManagerApi.setUpMessageHandlers(instanceManager: instanceManager); AssetResourceReader.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); - AssetResourceReaderDelegate.pigeon_setUpMessageHandlers(pigeon_instanceManager: instanceManager); + AssetResourceReaderDelegate.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -204,8 +202,7 @@ class PigeonInstanceManager { final int identifier = _nextUniqueIdentifier(); _identifiers[instance] = identifier; - _weakInstances[identifier] = - WeakReference(instance); + _weakInstances[identifier] = WeakReference(instance); _finalizer.attach(instance, identifier, detach: instance); final PigeonInternalProxyApiBaseClass copy = instance.pigeon_copy(); @@ -307,8 +304,7 @@ class PigeonInstanceManager { /// Whether this manager contains the given [identifier]. bool containsIdentifier(int identifier) { - return _weakInstances.containsKey(identifier) || - _strongInstances.containsKey(identifier); + return _weakInstances.containsKey(identifier) || _strongInstances.containsKey(identifier); } int _nextUniqueIdentifier() { @@ -325,7 +321,7 @@ class PigeonInstanceManager { class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) - : pigeonVar_binaryMessenger = binaryMessenger; + : pigeonVar_binaryMessenger = binaryMessenger; final BinaryMessenger? pigeonVar_binaryMessenger; @@ -338,9 +334,10 @@ class _PigeonInternalInstanceManagerApi { }) { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.PigeonInternalInstanceManager.removeStrongReference', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { @@ -348,14 +345,14 @@ class _PigeonInternalInstanceManagerApi { final List args = message! as List; final int arg_identifier = args[0]! as int; try { - (instanceManager ?? PigeonInstanceManager.instance) - .remove(arg_identifier); + (instanceManager ?? PigeonInstanceManager.instance).remove(arg_identifier); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -370,15 +367,10 @@ class _PigeonInternalInstanceManagerApi { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([identifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([identifier]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); } /// Clear the native `PigeonInstanceManager`. @@ -395,39 +387,33 @@ class _PigeonInternalInstanceManagerApi { final Future pigeonVar_sendFuture = pigeonVar_channel.send(null); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); } } class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { - const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInstanceManager instanceManager; - @override - void writeValue(WriteBuffer buffer, Object? value) { - if (value is PigeonInternalProxyApiBaseClass) { - buffer.putUint8(128); - writeValue(buffer, instanceManager.getIdentifier(value)); - } else { - super.writeValue(buffer, value); - } - } - @override - Object? readValueOfType(int type, ReadBuffer buffer) { - switch (type) { - case 128: - return instanceManager - .getInstanceWithWeakReference(readValue(buffer)! as int); - default: - return super.readValueOfType(type, buffer); - } - } -} - + const _PigeonInternalProxyApiBaseCodec(this.instanceManager); + final PigeonInstanceManager instanceManager; + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is PigeonInternalProxyApiBaseClass) { + buffer.putUint8(128); + writeValue(buffer, instanceManager.getIdentifier(value)); + } else { + super.writeValue(buffer, value); + } + } + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return instanceManager.getInstanceWithWeakReference(readValue(buffer)! as int); + default: + return super.readValueOfType(type, buffer); + } + } +} class _PigeonCodec extends StandardMessageCodec { const _PigeonCodec(); @@ -449,6 +435,7 @@ class _PigeonCodec extends StandardMessageCodec { } } } + /// Class for handling an instance of asynchronously reading bytes from /// a [PHAssetResourceManager](https://developer.apple.com/documentation/photos/phassetresourcemanager). class AssetResourceReader extends PigeonInternalProxyApiBaseClass { @@ -468,14 +455,9 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// Constructs a [AssetResourceReader]. @protected - AssetResourceReader.pigeon_new({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceReader; + AssetResourceReader.pigeon_new({super.pigeon_binaryMessenger, super.pigeon_instanceManager}) { + final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_defaultConstructor'; @@ -484,16 +466,13 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + ]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); }(); } @@ -502,13 +481,9 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// This should only be used by subclasses created by this library or to /// create copies for an [PigeonInstanceManager]. @protected - AssetResourceReader.pigeon_detached({ - super.pigeon_binaryMessenger, - super.pigeon_instanceManager, - }); + AssetResourceReader.pigeon_detached({super.pigeon_binaryMessenger, super.pigeon_instanceManager}); - late final _PigeonInternalProxyApiBaseCodec - _pigeonVar_codecAssetResourceReader = + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceReader = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); static void pigeon_setUpMessageHandlers({ @@ -517,15 +492,16 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { PigeonInstanceManager? pigeon_instanceManager, AssetResourceReader Function()? pigeon_newInstance, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_newInstance', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { @@ -533,8 +509,7 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { final List args = message! as List; final int arg_pigeon_instanceIdentifier = args[0]! as int; try { - (pigeon_instanceManager ?? PigeonInstanceManager.instance) - .addHostCreatedInstance( + (pigeon_instanceManager ?? PigeonInstanceManager.instance).addHostCreatedInstance( pigeon_newInstance?.call() ?? AssetResourceReader.pigeon_detached( pigeon_binaryMessenger: pigeon_binaryMessenger, @@ -547,7 +522,8 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -563,12 +539,8 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// `onCompletion` is called. /// /// See [PHAssetResourceManager.requestDataForAssetResource](https://developer.apple.com/documentation/photos/phassetresourcemanager/requestdata(for:options:datareceivedhandler:completionhandler:)?language=objc). - Future openRead( - String localIdentifier, - AssetResourceReaderDelegate delegate, - ) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceReader; + Future openRead(String localIdentifier, AssetResourceReaderDelegate delegate) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.openRead'; @@ -577,8 +549,11 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, localIdentifier, delegate]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + this, + localIdentifier, + delegate, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( @@ -593,8 +568,7 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { /// /// See [AssetResourceReader.requestImageDataAndOrientationForAsset](https://developer.apple.com/documentation/photos/phimagemanager/requestimagedataandorientation(for:options:resulthandler:)?changes=_6_4_2). Future readBytes(String localIdentifier) async { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _pigeonVar_codecAssetResourceReader; + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReader; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const pigeonVar_channelName = 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReader.readBytes'; @@ -603,8 +577,10 @@ class AssetResourceReader extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([this, localIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + this, + localIdentifier, + ]); final pigeonVar_replyList = await pigeonVar_sendFuture as List?; final Object? pigeonVar_replyValue = _extractReplyValueOrThrow( @@ -630,14 +606,9 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { factory AssetResourceReaderDelegate({ BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - required void Function( - AssetResourceReaderDelegate pigeon_instance, - Uint8List bytes, - ) onDataReceived, - required void Function( - AssetResourceReaderDelegate pigeon_instance, - String? error, - ) onCompletion, + required void Function(AssetResourceReaderDelegate pigeon_instance, Uint8List bytes) + onDataReceived, + required void Function(AssetResourceReaderDelegate pigeon_instance, String? error) onCompletion, }) { if (PigeonOverrides.assetResourceReaderDelegate_new != null) { return PigeonOverrides.assetResourceReaderDelegate_new!( @@ -661,8 +632,7 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { required this.onDataReceived, required this.onCompletion, }) { - final int pigeonVar_instanceIdentifier = - pigeon_instanceManager.addDartCreatedInstance(this); + final int pigeonVar_instanceIdentifier = pigeon_instanceManager.addDartCreatedInstance(this); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecAssetResourceReaderDelegate; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -673,16 +643,13 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { pigeonChannelCodec, binaryMessenger: pigeonVar_binaryMessenger, ); - final Future pigeonVar_sendFuture = - pigeonVar_channel.send([pigeonVar_instanceIdentifier]); + final Future pigeonVar_sendFuture = pigeonVar_channel.send([ + pigeonVar_instanceIdentifier, + ]); () async { final pigeonVar_replyList = await pigeonVar_sendFuture as List?; - _extractReplyValueOrThrow( - pigeonVar_replyList, - pigeonVar_channelName, - isNullValid: true, - ); + _extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true); }(); } @@ -698,8 +665,7 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { required this.onCompletion, }); - late final _PigeonInternalProxyApiBaseCodec - _pigeonVar_codecAssetResourceReaderDelegate = + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecAssetResourceReaderDelegate = _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); /// Provides the requested data. @@ -726,10 +692,7 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function( - AssetResourceReaderDelegate pigeon_instance, - Uint8List bytes, - ) onDataReceived; + final void Function(AssetResourceReaderDelegate pigeon_instance, Uint8List bytes) onDataReceived; /// Indicates the request for data has completed. /// @@ -755,33 +718,25 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { /// /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. - final void Function( - AssetResourceReaderDelegate pigeon_instance, - String? error, - ) onCompletion; + final void Function(AssetResourceReaderDelegate pigeon_instance, String? error) onCompletion; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, PigeonInstanceManager? pigeon_instanceManager, - void Function( - AssetResourceReaderDelegate pigeon_instance, - Uint8List bytes, - )? onDataReceived, - void Function( - AssetResourceReaderDelegate pigeon_instance, - String? error, - )? onCompletion, + void Function(AssetResourceReaderDelegate pigeon_instance, Uint8List bytes)? onDataReceived, + void Function(AssetResourceReaderDelegate pigeon_instance, String? error)? onCompletion, }) { - final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInstanceManager.instance); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onDataReceived', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onDataReceived', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { @@ -791,14 +746,17 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { args[0]! as AssetResourceReaderDelegate; final Uint8List arg_bytes = args[1]! as Uint8List; try { - (onDataReceived ?? arg_pigeon_instance.onDataReceived) - .call(arg_pigeon_instance, arg_bytes); + (onDataReceived ?? arg_pigeon_instance.onDataReceived).call( + arg_pigeon_instance, + arg_bytes, + ); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -806,9 +764,10 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { { final pigeonVar_channel = BasicMessageChannel( - 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onCompletion', - pigeonChannelCodec, - binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.cross_file_darwin.AssetResourceReaderDelegate.onCompletion', + pigeonChannelCodec, + binaryMessenger: binaryMessenger, + ); if (pigeon_clearHandlers) { pigeonVar_channel.setMessageHandler(null); } else { @@ -818,14 +777,14 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { args[0]! as AssetResourceReaderDelegate; final String? arg_error = args[1] as String?; try { - (onCompletion ?? arg_pigeon_instance.onCompletion) - .call(arg_pigeon_instance, arg_error); + (onCompletion ?? arg_pigeon_instance.onCompletion).call(arg_pigeon_instance, arg_error); return wrapResponse(empty: true); } on PlatformException catch (e) { return wrapResponse(error: e); } catch (e) { return wrapResponse( - error: PlatformException(code: 'error', message: e.toString())); + error: PlatformException(code: 'error', message: e.toString()), + ); } }); } @@ -842,4 +801,3 @@ class AssetResourceReaderDelegate extends PigeonInternalProxyApiBaseClass { ); } } - From ab90e7ae300b53bcccf30f11d6aa47635353a405 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 19:50:28 -0400 Subject: [PATCH 385/398] add pigeon impl to run on macos --- .../src/darwin_scoped_storage_cross_file.dart | 197 +++++++++++------- 1 file changed, 126 insertions(+), 71 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index deb37eb6ae60..7f5f7955213f 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -14,6 +14,7 @@ import 'package:objective_c/objective_c.dart'; import 'package:path/path.dart' as path; import 'byte_range_filter.dart'; +import 'cross_file_darwin_apis.g.dart'; import 'ffi_bindings.g.dart'; import 'security_scoped_resource.dart'; @@ -212,49 +213,91 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile ); } - final PHAssetResource? resource = _tryGetAssetResource(identifier: params.uri); - if (resource == null) { - return Stream.error( - Exception('Failed to start reading bytes from asset with identifier: ${params.uri}'), - ); + // TODO(bparrishMines): Thread merging is optional on macOS, so the FFI + // implementation is not guaranteed to work when it needs to switch to the + // platform thread from a native callback. + if (defaultTargetPlatform == TargetPlatform.macOS) { + return _openReadWithPigeon(); } - final streamController = StreamController(); + return _openReadWithFFI(); + } - final filter = ByteRangeFilter(start: 0, end: end); + @override + Future readAsBytes() { + // TODO(bparrishMines): Thread merging is optional on macOS, so the FFI + // implementation is not guaranteed to work when it needs to switch to the + // platform thread from a native callback. + if (defaultTargetPlatform == TargetPlatform.macOS) { + return _readBytesWithPigeon(); + } - void dataReceivedHandler(NSData data) { - final Uint8List bytes = _extractBytesToUint8List(data); + return _readBytesWithFFI(); + } - runOnPlatformThread(() { - final Uint8List inRangeBytes = filter.addBytes(bytes); - if (inRangeBytes.isNotEmpty) { - streamController.add(inRangeBytes); - } - }); - } + @override + Future readAsString({Encoding encoding = utf8}) => encoding.decodeStream(openRead()); - void completionHandler(NSError? error) { - runOnPlatformThread(() { - if (error != null) { - streamController.addError(Exception(error.localizedDescription.toDartString())); - } + @override + Future canRead() => exists(); - return streamController.close(); - }); + @override + Future exists() async => _tryGetAsset(identifier: params.uri) != null; + + @override + Future name() async { + if (_tryGetAssetResource(identifier: params.uri) case final PHAssetResource resource) { + return resource.originalFilename.toDartString(); } - PHAssetResourceManager.defaultManager().requestDataForAssetResource( - resource, - dataReceivedHandler: ObjCBlock_ffiVoid_NSData.blocking(dataReceivedHandler), - completionHandler: ObjCBlock_ffiVoid_NSError.blocking(completionHandler), + return null; + } + + @override + Future dispose() async { + // Reference to the asset does not need to be released. + } + + PHAsset? _tryGetAsset({required String identifier}) { + final PHFetchResult result = PHAsset.fetchAssetsWithLocalIdentifiers( + [params.uri].toNSArray(), ); + final ObjCObject? firstObject = result.firstObject; + if (firstObject != null) { + return PHAsset.as(firstObject); + } - return streamController.stream; + return null; } - @override - Future readAsBytes() { + PHAssetResource? _tryGetAssetResource({required String identifier}) { + if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { + final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); + final ObjCObject? firstObject = resources.firstObject; + + if (firstObject != null) { + return PHAssetResource.as(firstObject); + } + } + + return null; + } + + Uint8List _extractBytesToUint8List(NSData data) { + if (data.length == 0) { + return Uint8List(0); + } + + final Pointer uint8Pointer = data.bytes.cast(); + final Uint8List byteView = uint8Pointer.asTypedList(data.length); + return Uint8List.fromList(byteView); + } + + Future _readBytesWithPigeon() { + return AssetResourceReader().readBytes(params.uri); + } + + Future _readBytesWithFFI() { if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { final PHImageManager manager = PHImageManager.defaultManager(); final PHImageRequestOptions options = PHImageRequestOptions.new$(); @@ -275,7 +318,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile } else { runOnPlatformThread(() { bytesCompleter.completeError( - Exception('Failed to read byes from asset with identifier: ${params.uri}'), + Exception('Failed to read bytes from asset with identifier: ${params.uri}'), ); }); } @@ -292,65 +335,77 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile return bytesCompleter.future; } - throw Exception('Failed to read byes from asset with identifier: ${params.uri}'); + throw Exception('Failed to read bytes from asset with identifier: ${params.uri}'); } - @override - Future readAsString({Encoding encoding = utf8}) => encoding.decodeStream(openRead()); + Stream _openReadWithPigeon([int? start, int? end]) async* { + final resourceReader = AssetResourceReader(); - @override - Future canRead() => exists(); + final streamController = StreamController(); + final filter = ByteRangeFilter(start: start ?? 0, end: end); - @override - Future exists() async => _tryGetAsset(identifier: params.uri) != null; + final delegate = AssetResourceReaderDelegate( + onDataReceived: (_, Uint8List bytes) { + final Uint8List inRangeBytes = filter.addBytes(bytes); + if (inRangeBytes.isNotEmpty) { + streamController.add(inRangeBytes); + } + }, + onCompletion: (_, String? error) { + if (error != null) { + streamController.addError(Exception(error)); + } - @override - Future name() async { - if (_tryGetAssetResource(identifier: params.uri) case final PHAssetResource resource) { - return resource.originalFilename.toDartString(); + streamController.close(); + }, + ); + + final bool success = await resourceReader.openRead(params.uri, delegate); + if (!success) { + throw Exception('Failed to find asset with identifier: ${params.uri}'); } - return null; + yield* streamController.stream; } - PHAsset? _tryGetAsset({required String identifier}) { - final PHFetchResult result = PHAsset.fetchAssetsWithLocalIdentifiers( - [params.uri].toNSArray(), - ); - final ObjCObject? firstObject = result.firstObject; - if (firstObject != null) { - return PHAsset.as(firstObject); + Stream _openReadWithFFI([int? start, int? end]) { + final PHAssetResource? resource = _tryGetAssetResource(identifier: params.uri); + if (resource == null) { + return Stream.error(Exception('Failed to find resource with identifier: ${params.uri}')); } - return null; - } + final streamController = StreamController(); - PHAssetResource? _tryGetAssetResource({required String identifier}) { - if (_tryGetAsset(identifier: params.uri) case final PHAsset asset) { - final NSArray resources = PHAssetResource.assetResourcesForAsset(asset); - final ObjCObject? firstObject = resources.firstObject; + final filter = ByteRangeFilter(start: start ?? 0, end: end); - if (firstObject != null) { - return PHAssetResource.as(firstObject); - } + void dataReceivedHandler(NSData data) { + final Uint8List bytes = _extractBytesToUint8List(data); + + runOnPlatformThread(() { + final Uint8List inRangeBytes = filter.addBytes(bytes); + if (inRangeBytes.isNotEmpty) { + streamController.add(inRangeBytes); + } + }); } - return null; - } + void completionHandler(NSError? error) { + runOnPlatformThread(() { + if (error != null) { + streamController.addError(Exception(error.localizedDescription.toDartString())); + } - Uint8List _extractBytesToUint8List(NSData data) { - if (data.length == 0) { - return Uint8List(0); + return streamController.close(); + }); } - final Pointer uint8Pointer = data.bytes.cast(); - final Uint8List byteView = uint8Pointer.asTypedList(data.length); - return Uint8List.fromList(byteView); - } + PHAssetResourceManager.defaultManager().requestDataForAssetResource( + resource, + dataReceivedHandler: ObjCBlock_ffiVoid_NSData.blocking(dataReceivedHandler), + completionHandler: ObjCBlock_ffiVoid_NSError.blocking(completionHandler), + ); - @override - Future dispose() async { - // Reference to the asset does not need to be released. + return streamController.stream; } } From 31348b1122579d792d2707bc19e668c662c6870f Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 20:43:01 -0400 Subject: [PATCH 386/398] add tests back --- .../src/darwin_scoped_storage_cross_file.dart | 18 ++- .../cross_file/cross_file_darwin/pubspec.yaml | 2 + ...darwin_scoped_storage_cross_file_test.dart | 107 +++++++++++++ ..._scoped_storage_cross_file_test.mocks.dart | 151 ++++++++++++++++++ 4 files changed, 270 insertions(+), 8 deletions(-) create mode 100644 packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart create mode 100644 packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart diff --git a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart index 7f5f7955213f..7708a21ee91a 100644 --- a/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file_darwin/lib/src/darwin_scoped_storage_cross_file.dart @@ -217,10 +217,10 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile // implementation is not guaranteed to work when it needs to switch to the // platform thread from a native callback. if (defaultTargetPlatform == TargetPlatform.macOS) { - return _openReadWithPigeon(); + return _openReadWithPigeon(start, end); } - return _openReadWithFFI(); + return _openReadWithFFI(start, end); } @override @@ -338,7 +338,7 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile throw Exception('Failed to read bytes from asset with identifier: ${params.uri}'); } - Stream _openReadWithPigeon([int? start, int? end]) async* { + Stream _openReadWithPigeon([int? start, int? end]) { final resourceReader = AssetResourceReader(); final streamController = StreamController(); @@ -360,12 +360,14 @@ base class PhotoKitDarwinScopedStorageXFile extends DarwinScopedStorageXFile }, ); - final bool success = await resourceReader.openRead(params.uri, delegate); - if (!success) { - throw Exception('Failed to find asset with identifier: ${params.uri}'); - } + resourceReader.openRead(params.uri, delegate).then((bool success) { + if (!success) { + streamController.addError(Exception('Failed to find asset with identifier: ${params.uri}')); + streamController.close(); + } + }); - yield* streamController.stream; + return streamController.stream; } Stream _openReadWithFFI([int? start, int? end]) { diff --git a/packages/cross_file/cross_file_darwin/pubspec.yaml b/packages/cross_file/cross_file_darwin/pubspec.yaml index f02e979a087b..f360a342ae41 100644 --- a/packages/cross_file/cross_file_darwin/pubspec.yaml +++ b/packages/cross_file/cross_file_darwin/pubspec.yaml @@ -37,9 +37,11 @@ dependencies: path: ^1.9.1 dev_dependencies: + build_runner: ^2.15.1 ffigen: ^21.0.0 flutter_test: sdk: flutter + mockito: ^5.6.4 pigeon: ^27.3.0 topics: diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart new file mode 100644 index 000000000000..e7cf8cb417e6 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -0,0 +1,107 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:typed_data'; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; +import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart'; + +@GenerateMocks([AssetResourceReader, AssetResourceReaderDelegate]) +void main() { + setUp(() { + PigeonOverrides.pigeon_reset(); + }); + + group('openRead pigeon', () { + test('correctly reads all bytes with null start and null end', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.macOS; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), + ); + + final MockAssetResourceReaderDelegate delegate = setUpReader(); + + final Stream stream = file.openRead(); + + final bytes = Uint8List.fromList([1, 2, 3]); + delegate.onDataReceived(delegate, bytes); + delegate.onCompletion(delegate, null); + + expect( + await stream.reduce( + (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), + ), + bytes, + ); + + debugDefaultTargetPlatformOverride = null; + }); + + test('correctly reads desired sublist', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.macOS; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), + ); + + final MockAssetResourceReaderDelegate delegate = setUpReader(); + + final bytes = Uint8List.fromList([0, 1, 2, 3, 4]); + final Stream stream = file.openRead(1, 4); + + // Ignore byte before desired sublist. + delegate.onDataReceived(delegate, Uint8List.fromList([bytes[0]])); + // Read byte at start of desired sublist. + delegate.onDataReceived(delegate, Uint8List.fromList([bytes[1]])); + // Read byte between start and end of desired sublist. + delegate.onDataReceived(delegate, Uint8List.fromList([bytes[2]])); + // Read byte at end of desire sublist + delegate.onDataReceived(delegate, Uint8List.fromList([bytes[3]])); + // Ignore byte after desired sublist. + delegate.onDataReceived(delegate, Uint8List.fromList([bytes[4]])); + delegate.onCompletion(delegate, null); + + expect( + await stream.reduce( + (Uint8List first, Uint8List second) => Uint8List.fromList([...first, ...second]), + ), + bytes.sublist(1, 4), + ); + + debugDefaultTargetPlatformOverride = null; + }); + }); +} + +MockAssetResourceReaderDelegate setUpReader() { + final reader = MockAssetResourceReader(); + final readerDelegate = MockAssetResourceReaderDelegate(); + + when(reader.openRead('id', readerDelegate)).thenAnswer((_) async { + return true; + }); + + PigeonOverrides.assetResourceReader_new = () { + return reader; + }; + PigeonOverrides.assetResourceReaderDelegate_new = + ({ + required void Function(AssetResourceReaderDelegate instance, Uint8List bytes) + onDataReceived, + required void Function(AssetResourceReaderDelegate instance, String? error) onCompletion, + }) { + when(readerDelegate.onDataReceived).thenReturn(onDataReceived); + when(readerDelegate.onCompletion).thenReturn(onCompletion); + return readerDelegate; + }; + + return readerDelegate; +} diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart new file mode 100644 index 000000000000..0b4c0ecff369 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart @@ -0,0 +1,151 @@ +// Mocks generated by Mockito 5.4.6 from annotations +// in cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; +import 'dart:typed_data' as _i4; + +import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: type=lint +// ignore_for_file: avoid_redundant_argument_values +// ignore_for_file: avoid_setters_without_getters +// ignore_for_file: comment_references +// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: implementation_imports +// ignore_for_file: invalid_use_of_visible_for_testing_member +// ignore_for_file: must_be_immutable +// ignore_for_file: prefer_const_constructors +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class +// ignore_for_file: invalid_use_of_internal_member + +class _FakePigeonInstanceManager_0 extends _i1.SmartFake + implements _i2.PigeonInstanceManager { + _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeAssetResourceReader_1 extends _i1.SmartFake + implements _i2.AssetResourceReader { + _FakeAssetResourceReader_1(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +class _FakeAssetResourceReaderDelegate_2 extends _i1.SmartFake + implements _i2.AssetResourceReaderDelegate { + _FakeAssetResourceReaderDelegate_2(Object parent, Invocation parentInvocation) + : super(parent, parentInvocation); +} + +/// A class which mocks [AssetResourceReader]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockAssetResourceReader extends _i1.Mock + implements _i2.AssetResourceReader { + MockAssetResourceReader() { + _i1.throwOnMissingStub(this); + } + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i3.Future openRead( + String? localIdentifier, + _i2.AssetResourceReaderDelegate? delegate, + ) => + (super.noSuchMethod( + Invocation.method(#openRead, [localIdentifier, delegate]), + returnValue: _i3.Future.value(false), + ) + as _i3.Future); + + @override + _i3.Future<_i4.Uint8List> readBytes(String? localIdentifier) => + (super.noSuchMethod( + Invocation.method(#readBytes, [localIdentifier]), + returnValue: _i3.Future<_i4.Uint8List>.value(_i4.Uint8List(0)), + ) + as _i3.Future<_i4.Uint8List>); + + @override + _i2.AssetResourceReader pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeAssetResourceReader_1( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.AssetResourceReader); +} + +/// A class which mocks [AssetResourceReaderDelegate]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockAssetResourceReaderDelegate extends _i1.Mock + implements _i2.AssetResourceReaderDelegate { + MockAssetResourceReaderDelegate() { + _i1.throwOnMissingStub(this); + } + + @override + void Function(_i2.AssetResourceReaderDelegate, _i4.Uint8List) + get onDataReceived => + (super.noSuchMethod( + Invocation.getter(#onDataReceived), + returnValue: + ( + _i2.AssetResourceReaderDelegate pigeon_instance, + _i4.Uint8List bytes, + ) {}, + ) + as void Function(_i2.AssetResourceReaderDelegate, _i4.Uint8List)); + + @override + void Function(_i2.AssetResourceReaderDelegate, String?) get onCompletion => + (super.noSuchMethod( + Invocation.getter(#onCompletion), + returnValue: + ( + _i2.AssetResourceReaderDelegate pigeon_instance, + String? error, + ) {}, + ) + as void Function(_i2.AssetResourceReaderDelegate, String?)); + + @override + _i2.PigeonInstanceManager get pigeon_instanceManager => + (super.noSuchMethod( + Invocation.getter(#pigeon_instanceManager), + returnValue: _FakePigeonInstanceManager_0( + this, + Invocation.getter(#pigeon_instanceManager), + ), + ) + as _i2.PigeonInstanceManager); + + @override + _i2.AssetResourceReaderDelegate pigeon_copy() => + (super.noSuchMethod( + Invocation.method(#pigeon_copy, []), + returnValue: _FakeAssetResourceReaderDelegate_2( + this, + Invocation.method(#pigeon_copy, []), + ), + ) + as _i2.AssetResourceReaderDelegate); +} From cad1509b25288261c43d7ca39a8153774a3c75f9 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 20:47:10 -0400 Subject: [PATCH 387/398] add readbytes test --- ...darwin_scoped_storage_cross_file_test.dart | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart index e7cf8cb417e6..aaa01d742189 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -19,6 +19,25 @@ void main() { PigeonOverrides.pigeon_reset(); }); + test('readBytes', () async { + debugDefaultTargetPlatformOverride = TargetPlatform.macOS; + + final file = DarwinScopedStorageXFile( + DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), + ); + + final reader = MockAssetResourceReader(); + final bytes = Uint8List.fromList([1, 2, 3]); + when(reader.readBytes('id')).thenAnswer((_) => Future.value(bytes)); + PigeonOverrides.assetResourceReader_new = () { + return reader; + }; + + expect(await file.readAsBytes(), bytes); + + debugDefaultTargetPlatformOverride = null; + }); + group('openRead pigeon', () { test('correctly reads all bytes with null start and null end', () async { debugDefaultTargetPlatformOverride = TargetPlatform.macOS; @@ -27,7 +46,7 @@ void main() { DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), ); - final MockAssetResourceReaderDelegate delegate = setUpReader(); + final MockAssetResourceReaderDelegate delegate = setUpReaderDelegate(); final Stream stream = file.openRead(); @@ -52,7 +71,7 @@ void main() { DarwinScopedStorageXFileCreationParams.photoKit(localIdentifier: 'id'), ); - final MockAssetResourceReaderDelegate delegate = setUpReader(); + final MockAssetResourceReaderDelegate delegate = setUpReaderDelegate(); final bytes = Uint8List.fromList([0, 1, 2, 3, 4]); final Stream stream = file.openRead(1, 4); @@ -81,7 +100,7 @@ void main() { }); } -MockAssetResourceReaderDelegate setUpReader() { +MockAssetResourceReaderDelegate setUpReaderDelegate() { final reader = MockAssetResourceReader(); final readerDelegate = MockAssetResourceReaderDelegate(); From feff9f30462b688fdb29dd94fbb5ced866c43aec Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 21:04:32 -0400 Subject: [PATCH 388/398] update excerpts --- packages/cross_file/cross_file/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index 90dd9f9b3cea..d3ef88e826c4 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -21,7 +21,7 @@ Example: ```dart -final file = XFile.fromUri(Uri.file('assets/hello.txt')); +final file = XFile.fileSystem(path: 'assets/hello.txt'); debugPrint('File information:'); debugPrint('- URI: ${file.uri}'); @@ -79,11 +79,11 @@ switch (CrossFile.implementation) { final params = WebScopedStorageXFileCreationParams.fromObjectUrl( objectUrl: 'blob:https://some/url:for/file', ); - file = XFile.fromCreationParams(params); + file = ScopedStorageXFile.fromCreationParams(params); case CrossFileDarwin(): file = ScopedStorageXFile.fromUri(Uri.file('/my/file.txt')); default: - file = XFile.fromUri(Uri.file('/my/file.txt')); + file = XFile.fileSystem(path: '/my/file.txt'); } await file From cf91564f1c0e4a7f9bb6cffea183a8f3a2483a21 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 11 Aug 2026 21:09:22 -0400 Subject: [PATCH 389/398] update readme --- packages/cross_file/cross_file/README.md | 16 +++++++--------- .../scoped_storage_cross_file.dart | 3 --- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/packages/cross_file/cross_file/README.md b/packages/cross_file/cross_file/README.md index d3ef88e826c4..f3c34085b519 100644 --- a/packages/cross_file/cross_file/README.md +++ b/packages/cross_file/cross_file/README.md @@ -6,16 +6,14 @@ An abstraction to allow working with files across multiple platforms. [![pub package](https://img.shields.io/pub/v/cross_file.svg)](https://pub.dartlang.org/packages/cross_file) -A Flutter plugin that manages files and interactions with file dialogs. - | | Android | iOS | Linux | macOS | Web | Windows | |-------------|---------|---------|-------|--------|-----|-------------| | **Support** | SDK 24+ | iOS 13+ | Any | 10.15+ | Any | Windows 10+ | ## Usage -Instantiate a `XFile` using a uri or path and use its methods and properties to -access the file and its metadata. +Instantiate a `XFile` using a uri or path and use its methods and properties to access the file and +its metadata. Example: @@ -59,14 +57,14 @@ import 'package:cross_file_web/cross_file_web.dart'; ``` Now, additional features can be accessed through the platform implementations. Classes -[XFile], [XDirectory], [ScopedStorageXFile], and [ScopedStorageXDirectory] pass their -functionality to a class provided by the current platform. Below are a couple of ways to access -additional functionality provided by the platform and is followed by an example. +[FileSystemXFile], [FileSystemXDirectory], [ScopedStorageXFile], and [ScopedStorageXDirectory] pass +their functionality to a class provided by the current platform. Below are a couple of ways to +access additional functionality provided by the platform and is followed by an example. 1. Pass a creation params class provided by a platform implementation to a `fromCreationParams` constructor (e.g. `XFile.fromCreationParams`, `XDirectory.fromCreationParams`, etc.). -2. Call methods on an implementation of a class by using `getExtension`/`maybeGetExtension` methods (e.g. - `XFile.getExtension`, `XDirectory.maybeGetExtension`, etc.). +2. Call methods on an implementation of a class by using `getExtension` method (e.g. + `XFile.getExtension`, `XDirectory.getExtension`, etc.). Below is an example of using additional iOS/macOS and Web features for a `XFile`. diff --git a/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart b/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart index 0f7ac0efb15f..b6be82e33165 100644 --- a/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/scoped_storage/scoped_storage_cross_file.dart @@ -7,9 +7,6 @@ import 'package:flutter/foundation.dart' show immutable, internal; import '../cross_file.dart'; -// TODO: What is scoped storage? in readme. This plugin provides to implementaiton: -// Filesystem vs scoped storage. - /// A reference to a local data resource within a device's scoped storage. /// /// Scoped storage limits app access to external storage and apps may lose From 8d7ff9233a01908058f990327bb044e214b0af0d Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:00:11 -0400 Subject: [PATCH 390/398] add breaking changes --- packages/cross_file/cross_file/CHANGELOG.md | 18 ++++++++++++------ .../file_system_cross_directory.dart | 3 +++ .../file_system/file_system_cross_file.dart | 3 +++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/cross_file/cross_file/CHANGELOG.md b/packages/cross_file/cross_file/CHANGELOG.md index 816dd7422428..0fc7f46a39c9 100644 --- a/packages/cross_file/cross_file/CHANGELOG.md +++ b/packages/cross_file/cross_file/CHANGELOG.md @@ -2,12 +2,18 @@ * Updates `cross_file` to a package-separated federated plugin. * Adds `XDirectory` to access file containers. -* Adds file implementation for scoped storage APIs that use ephemeral URLS. See `ScopedStorageXFile` - and `ScopedStorageXDirector`. -* **Breaking Change** Replaces `XFile(String path)` with `XFile.fromPath(String path)`. -* **Breaking Change** Removes `XFile.fromDatag`. -* **Breaking Change** Removes `XFile.saveTo`. -* **Breaking Change** Removes `mimeType` and `path`. +* Adds implementation for file systems. See `FileSystemXFile` and `FileSystemXDirectory`. +* Adds implementation for scoped storage APIs that use ephemeral URLS. See `ScopedStorageXFile` + and `ScopedStorageXDirectory`. +* **Breaking Change** Replaces `XFile(String path)` with `XFile.fileSystem({required String path})` + or `FileSystem(String path)`. +* **Breaking Change** Removes `XFile.fromData`. `XFile`s can no longer be instantiated with a + `Uint8List`. For web, see README for an example to create one from a `Blob`/`File`. +* **Breaking Change** Removes `XFile.saveTo()`. `FileSystemXFile.writeAsBytes` has been added + and the web implementation can use `WebScopedStorageXFileExtension.download`. See README to see + how to access platform-specific feature. +* **Breaking Change** Removes `XFile.mimeType`. +* **Breaking Change** Removes `XFile.path`. This has been replaced by `FileSystemXFile.path`. * **Breaking Change** Changes `XFile.name` to return `Future` rather than `String`. ## 0.3.5+4 diff --git a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart index c67239cdc0d5..7da699627915 100644 --- a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart +++ b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_directory.dart @@ -76,6 +76,9 @@ base class FileSystemXDirectory extends XDirectory { @internal const FileSystemXDirectory.fromPlatform(PlatformFileSystemXDirectory super.platform); + /// The path of the directory. + String get path => platform.params.path; + @internal @override PlatformFileSystemXDirectory get platform => super.platform as PlatformFileSystemXDirectory; diff --git a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart index 6ba47fae9c82..003f4787467d 100644 --- a/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart +++ b/packages/cross_file/cross_file/lib/src/file_system/file_system_cross_file.dart @@ -80,6 +80,9 @@ base class FileSystemXFile extends XFile { @override PlatformFileSystemXFile get platform => super.platform as PlatformFileSystemXFile; + /// The path of the file. + String get path => platform.params.path; + /// Writes a list of bytes to a file. /// /// Platforms may throw an exception if there is an error opening or writing From 87e5c7493e61bc37ecec2751cfd1977ecd879b10 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:07:10 -0400 Subject: [PATCH 391/398] unused import --- .../test/photo_kit_darwin_scoped_storage_cross_file_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart index aaa01d742189..c8af03b6bb92 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.dart @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'dart:typed_data'; - import 'package:cross_file_darwin/src/cross_file_darwin_apis.g.dart'; import 'package:cross_file_darwin/src/darwin_scoped_storage_cross_file.dart'; import 'package:flutter/foundation.dart'; From 71f7ab675f7319bf4567c91015b084d3ec27ee3a Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:11:59 -0400 Subject: [PATCH 392/398] remove darwin tests that aren't used --- .../darwin/Tests/CrossFileDarwinTests.swift | 22 ------------------- .../ios/Runner.xcodeproj/project.pbxproj | 12 ---------- .../example/ios/RunnerTests/Info.plist | 22 ------------------- 3 files changed, 56 deletions(-) delete mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift delete mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift deleted file mode 100644 index a222c2c29a14..000000000000 --- a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The Flutter Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import Testing - -@testable import cross_file_darwin - -#if os(iOS) - import Flutter -#elseif os(macOS) - import FlutterMacOS -#else - #error("Unsupported platform.") -#endif - -// Placeholder for adding tests. -struct CrossFileDarwinTests { - @Test func placeHoldertTest() throws { - #expect(true == true) - } -} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index b07ddad16ba1..b8ece5559f1d 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; - 8F2171F72F21A5270014CE68 /* CrossFileDarwinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -53,7 +52,6 @@ 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../darwin/cross_file_darwin; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinTests.swift; path = ../../darwin/Tests/CrossFileDarwinTests.swift; sourceTree = SOURCE_ROOT; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -82,14 +80,6 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 331C8082294A63A400263BE5 /* RunnerTests */ = { - isa = PBXGroup; - children = ( - 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */, - ); - path = RunnerTests; - sourceTree = ""; - }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -110,7 +100,6 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, - 331C8082294A63A400263BE5 /* RunnerTests */, DB75EE80F48401E65664EBB7 /* Pods */, ); sourceTree = ""; @@ -293,7 +282,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 8F2171F72F21A5270014CE68 /* CrossFileDarwinTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist deleted file mode 100644 index 64d65ca49577..000000000000 --- a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist +++ /dev/null @@ -1,22 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - - From 1634e7d7fa9e2670e91eb441d9e71a11f4f7f666 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:12:42 -0400 Subject: [PATCH 393/398] formatting --- ..._scoped_storage_cross_file_test.mocks.dart | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart index 0b4c0ecff369..71020daac235 100644 --- a/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart +++ b/packages/cross_file/cross_file_darwin/test/photo_kit_darwin_scoped_storage_cross_file_test.mocks.dart @@ -24,14 +24,12 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: subtype_of_sealed_class // ignore_for_file: invalid_use_of_internal_member -class _FakePigeonInstanceManager_0 extends _i1.SmartFake - implements _i2.PigeonInstanceManager { +class _FakePigeonInstanceManager_0 extends _i1.SmartFake implements _i2.PigeonInstanceManager { _FakePigeonInstanceManager_0(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakeAssetResourceReader_1 extends _i1.SmartFake - implements _i2.AssetResourceReader { +class _FakeAssetResourceReader_1 extends _i1.SmartFake implements _i2.AssetResourceReader { _FakeAssetResourceReader_1(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } @@ -45,8 +43,7 @@ class _FakeAssetResourceReaderDelegate_2 extends _i1.SmartFake /// A class which mocks [AssetResourceReader]. /// /// See the documentation for Mockito's code generation for more information. -class MockAssetResourceReader extends _i1.Mock - implements _i2.AssetResourceReader { +class MockAssetResourceReader extends _i1.Mock implements _i2.AssetResourceReader { MockAssetResourceReader() { _i1.throwOnMissingStub(this); } @@ -63,10 +60,7 @@ class MockAssetResourceReader extends _i1.Mock as _i2.PigeonInstanceManager); @override - _i3.Future openRead( - String? localIdentifier, - _i2.AssetResourceReaderDelegate? delegate, - ) => + _i3.Future openRead(String? localIdentifier, _i2.AssetResourceReaderDelegate? delegate) => (super.noSuchMethod( Invocation.method(#openRead, [localIdentifier, delegate]), returnValue: _i3.Future.value(false), @@ -85,10 +79,7 @@ class MockAssetResourceReader extends _i1.Mock _i2.AssetResourceReader pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeAssetResourceReader_1( - this, - Invocation.method(#pigeon_copy, []), - ), + returnValue: _FakeAssetResourceReader_1(this, Invocation.method(#pigeon_copy, [])), ) as _i2.AssetResourceReader); } @@ -96,22 +87,16 @@ class MockAssetResourceReader extends _i1.Mock /// A class which mocks [AssetResourceReaderDelegate]. /// /// See the documentation for Mockito's code generation for more information. -class MockAssetResourceReaderDelegate extends _i1.Mock - implements _i2.AssetResourceReaderDelegate { +class MockAssetResourceReaderDelegate extends _i1.Mock implements _i2.AssetResourceReaderDelegate { MockAssetResourceReaderDelegate() { _i1.throwOnMissingStub(this); } @override - void Function(_i2.AssetResourceReaderDelegate, _i4.Uint8List) - get onDataReceived => + void Function(_i2.AssetResourceReaderDelegate, _i4.Uint8List) get onDataReceived => (super.noSuchMethod( Invocation.getter(#onDataReceived), - returnValue: - ( - _i2.AssetResourceReaderDelegate pigeon_instance, - _i4.Uint8List bytes, - ) {}, + returnValue: (_i2.AssetResourceReaderDelegate pigeon_instance, _i4.Uint8List bytes) {}, ) as void Function(_i2.AssetResourceReaderDelegate, _i4.Uint8List)); @@ -119,11 +104,7 @@ class MockAssetResourceReaderDelegate extends _i1.Mock void Function(_i2.AssetResourceReaderDelegate, String?) get onCompletion => (super.noSuchMethod( Invocation.getter(#onCompletion), - returnValue: - ( - _i2.AssetResourceReaderDelegate pigeon_instance, - String? error, - ) {}, + returnValue: (_i2.AssetResourceReaderDelegate pigeon_instance, String? error) {}, ) as void Function(_i2.AssetResourceReaderDelegate, String?)); From 076e08e1883d8db7c1e492acd0aacaf7dcb5c8d0 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:14:29 -0400 Subject: [PATCH 394/398] unused import --- .../lib/src/platform_cross_directory.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart index 6883b6fc4840..0dab8f86ccd5 100644 --- a/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart +++ b/packages/cross_file/cross_file_platform_interface/lib/src/platform_cross_directory.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'package:flutter/foundation.dart' show immutable, protected; -import 'cross_file_platform.dart'; import 'platform_cross_entity.dart'; /// Object specifying creation parameters for creating a [PlatformXDirectory]. From 3f6f303d6f9ce3b6653e1416c10c6ba5c9c78f04 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 13:28:36 -0400 Subject: [PATCH 395/398] add license to darwin ffi --- .../Sources/cross_file_darwin_objc/ffi_bindings.g.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m index f8b5fc0d5efc..e28f469e4478 100644 --- a/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m +++ b/packages/cross_file/cross_file_darwin/darwin/cross_file_darwin/Sources/cross_file_darwin_objc/ffi_bindings.g.m @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #import #import #import From ec62032328c9a8d08bfde81b7d76e808ed77cf85 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:19:45 -0400 Subject: [PATCH 396/398] Revert "remove darwin tests that aren't used" This reverts commit 71f7ab675f7319bf4567c91015b084d3ec27ee3a. --- .../darwin/Tests/CrossFileDarwinTests.swift | 22 +++++++++++++++++++ .../ios/Runner.xcodeproj/project.pbxproj | 12 ++++++++++ .../example/ios/RunnerTests/Info.plist | 22 +++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift create mode 100644 packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist diff --git a/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift new file mode 100644 index 000000000000..a222c2c29a14 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/darwin/Tests/CrossFileDarwinTests.swift @@ -0,0 +1,22 @@ +// Copyright 2013 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Testing + +@testable import cross_file_darwin + +#if os(iOS) + import Flutter +#elseif os(macOS) + import FlutterMacOS +#else + #error("Unsupported platform.") +#endif + +// Placeholder for adding tests. +struct CrossFileDarwinTests { + @Test func placeHoldertTest() throws { + #expect(true == true) + } +} diff --git a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj index b8ece5559f1d..b07ddad16ba1 100644 --- a/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/cross_file/cross_file_darwin/example/ios/Runner.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; + 8F2171F72F21A5270014CE68 /* CrossFileDarwinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -52,6 +53,7 @@ 78DABEA22ED26510000E7860 /* cross_file_darwin */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = cross_file_darwin; path = ../../darwin/cross_file_darwin; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = CrossFileDarwinTests.swift; path = ../../darwin/Tests/CrossFileDarwinTests.swift; sourceTree = SOURCE_ROOT; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -80,6 +82,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 8F2171F52F21A5270014CE68 /* CrossFileDarwinTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( @@ -100,6 +110,7 @@ 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, DB75EE80F48401E65664EBB7 /* Pods */, ); sourceTree = ""; @@ -282,6 +293,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 8F2171F72F21A5270014CE68 /* CrossFileDarwinTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist new file mode 100644 index 000000000000..64d65ca49577 --- /dev/null +++ b/packages/cross_file/cross_file_darwin/example/ios/RunnerTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + From 796674309c29314b345559be57a3e7d446e308ee Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:25:22 -0400 Subject: [PATCH 397/398] fix android tests --- .../packages/crossfileandroid/proxies/ContentResolverTest.kt | 2 +- .../packages/crossfileandroid/proxies/DocumentFileTest.kt | 2 +- .../packages/crossfileandroid/proxies/InputStreamTest.kt | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt index 9a440ec717f8..0c7c939a283b 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/ContentResolverTest.kt @@ -6,7 +6,7 @@ package dev.flutter.packages.crossfileandroid.proxies import android.content.ContentResolver import android.net.Uri -import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.TestProxyApiRegistrar import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt index d08a6f2e5504..5f45b9ecd81b 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/DocumentFileTest.kt @@ -6,7 +6,7 @@ package dev.flutter.packages.crossfileandroid.proxies import android.net.Uri import androidx.documentfile.provider.DocumentFile -import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.TestProxyApiRegistrar import kotlin.test.Test import kotlin.test.assertEquals import org.mockito.Mockito.mockStatic diff --git a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt index 11b7e2507f20..e3797ab3fed7 100644 --- a/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt +++ b/packages/cross_file/cross_file_android/android/src/test/kotlin/dev/flutter/packages/crossfileandroid/proxies/InputStreamTest.kt @@ -4,13 +4,12 @@ package dev.flutter.packages.crossfileandroid.proxies -import dev.flutter.packages.cross_file_android.TestProxyApiRegistrar +import dev.flutter.packages.crossfileandroid.TestProxyApiRegistrar import java.io.ByteArrayInputStream import java.io.InputStream import kotlin.test.Test import kotlin.test.assertEquals import org.mockito.ArgumentCaptor -import org.mockito.kotlin.capture import org.mockito.kotlin.mock import org.mockito.kotlin.whenever From 74a5fda517b65625beba4a986a4fe067ac931795 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Thu, 13 Aug 2026 15:12:00 -0400 Subject: [PATCH 398/398] add cross_file_web because it uses chrome for flutter --- script/configs/windows_unit_tests_exceptions.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/script/configs/windows_unit_tests_exceptions.yaml b/script/configs/windows_unit_tests_exceptions.yaml index a2b6327d6ec4..a075e6a2d178 100644 --- a/script/configs/windows_unit_tests_exceptions.yaml +++ b/script/configs/windows_unit_tests_exceptions.yaml @@ -7,6 +7,7 @@ # Chrome, which isn't currently supported by web infrastructure. # TODO(ditman): Fix this in the repo tooling. - camera_web +- cross_file_web - file_selector_web - google_maps_flutter_web - google_sign_in_web