Merge branch 'issue/94051_navigation_delegate_typedefs' into intf_nav_update
diff --git a/.ci/flutter_master.version b/.ci/flutter_master.version
index 20cb21b..a9baeda 100644
--- a/.ci/flutter_master.version
+++ b/.ci/flutter_master.version
@@ -1 +1 @@
-4e8a28d29db7c26988c58ecaa692cb79f5e71394
+99475b1b0bee6ab09d0282b255c6b8c7e01ca4fe
diff --git a/.cirrus.yml b/.cirrus.yml
index 7a8e31d..01de99c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -64,7 +64,7 @@
 macos_arm_template: &MACOS_ARM_TEMPLATE
   << : *MACOS_TEMPLATE
   macos_instance:
-    image: ghcr.io/cirruslabs/macos-monterey-xcode:13.4
+    image: ghcr.io/cirruslabs/macos-ventura-xcode:14
 
 # Light-workload Linux tasks.
 # These use default machines, with fewer CPUs, to reduce pressure on the
diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md
index 33e2b61..986f5c0 100644
--- a/packages/image_picker/image_picker_ios/CHANGELOG.md
+++ b/packages/image_picker/image_picker_ios/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.8.6+1
+
+* Fixes issue with crashing the app when picking images with PHPicker without providing `Photo Library Usage` permission.
+
 ## 0.8.6
 
 * Adds `requestFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission.
diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m
index 688f5fb..e04c4f2 100644
--- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m
+++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m
@@ -22,7 +22,7 @@
   PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
                                                  withIdentifier:UTTypeWebP.identifier];
 
-  [self verifySavingImageWithPickerResult:result];
+  [self verifySavingImageWithPickerResult:result fullMetadata:YES];
 }
 
 - (void)testSavePNGImage API_AVAILABLE(ios(14)) {
@@ -32,7 +32,7 @@
   PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
                                                  withIdentifier:UTTypeWebP.identifier];
 
-  [self verifySavingImageWithPickerResult:result];
+  [self verifySavingImageWithPickerResult:result fullMetadata:YES];
 }
 
 - (void)testSaveJPGImage API_AVAILABLE(ios(14)) {
@@ -42,7 +42,7 @@
   PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
                                                  withIdentifier:UTTypeWebP.identifier];
 
-  [self verifySavingImageWithPickerResult:result];
+  [self verifySavingImageWithPickerResult:result fullMetadata:YES];
 }
 
 - (void)testSaveGIFImage API_AVAILABLE(ios(14)) {
@@ -52,7 +52,21 @@
   PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
                                                  withIdentifier:UTTypeWebP.identifier];
 
-  [self verifySavingImageWithPickerResult:result];
+  [self verifySavingImageWithPickerResult:result fullMetadata:YES];
+}
+
+- (void)testSavePNGImageWithoutFullMetadata API_AVAILABLE(ios(14)) {
+  id photoAssetUtil = OCMClassMock([PHAsset class]);
+
+  NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage"
+                                                             withExtension:@"png"];
+  NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL];
+  PHPickerResult *result = [self createPickerResultWithProvider:itemProvider
+                                                 withIdentifier:UTTypeWebP.identifier];
+
+  [self verifySavingImageWithPickerResult:result fullMetadata:NO];
+  OCMVerify(times(0), [photoAssetUtil fetchAssetsWithLocalIdentifiers:[OCMArg any]
+                                                              options:[OCMArg any]]);
 }
 
 /**
@@ -79,7 +93,8 @@
  *
  * @param result the picker result
  */
-- (void)verifySavingImageWithPickerResult:(PHPickerResult *)result API_AVAILABLE(ios(14)) {
+- (void)verifySavingImageWithPickerResult:(PHPickerResult *)result
+                             fullMetadata:(BOOL)fullMetadata API_AVAILABLE(ios(14)) {
   XCTestExpectation *pathExpectation = [self expectationWithDescription:@"Path was created"];
 
   FLTPHPickerSaveImageToPathOperation *operation = [[FLTPHPickerSaveImageToPathOperation alloc]
@@ -87,6 +102,7 @@
                 maxHeight:@100
                  maxWidth:@100
       desiredImageQuality:@100
+             fullMetadata:fullMetadata
            savedPathBlock:^(NSString *savedPath) {
              if ([[NSFileManager defaultManager] fileExistsAtPath:savedPath]) {
                [pathExpectation fulfill];
diff --git a/packages/image_picker/image_picker_ios/example/lib/main.dart b/packages/image_picker/image_picker_ios/example/lib/main.dart
index c5372b8..440f2f1 100755
--- a/packages/image_picker/image_picker_ios/example/lib/main.dart
+++ b/packages/image_picker/image_picker_ios/example/lib/main.dart
@@ -93,10 +93,15 @@
       await _displayPickImageDialog(context!,
           (double? maxWidth, double? maxHeight, int? quality) async {
         try {
-          final List<XFile>? pickedFileList = await _picker.getMultiImage(
-            maxWidth: maxWidth,
-            maxHeight: maxHeight,
-            imageQuality: quality,
+          final List<XFile> pickedFileList =
+              await _picker.getMultiImageWithOptions(
+            options: MultiImagePickerOptions(
+              imageOptions: ImageOptions(
+                maxWidth: maxWidth,
+                maxHeight: maxHeight,
+                imageQuality: quality,
+              ),
+            ),
           );
           setState(() {
             _imageFileList = pickedFileList;
@@ -111,11 +116,13 @@
       await _displayPickImageDialog(context!,
           (double? maxWidth, double? maxHeight, int? quality) async {
         try {
-          final XFile? pickedFile = await _picker.getImage(
+          final XFile? pickedFile = await _picker.getImageFromSource(
             source: source,
-            maxWidth: maxWidth,
-            maxHeight: maxHeight,
-            imageQuality: quality,
+            options: ImagePickerOptions(
+              maxWidth: maxWidth,
+              maxHeight: maxHeight,
+              imageQuality: quality,
+            ),
           );
           setState(() {
             _setImageFileListFromFile(pickedFile);
diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m
index fa1bb66..27b06ba 100644
--- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m
+++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m
@@ -490,14 +490,15 @@
 
     for (int i = 0; i < results.count; i++) {
       PHPickerResult *result = results[i];
-      FLTPHPickerSaveImageToPathOperation *operation =
-          [[FLTPHPickerSaveImageToPathOperation alloc] initWithResult:result
-                                                            maxHeight:maxHeight
-                                                             maxWidth:maxWidth
-                                                  desiredImageQuality:desiredImageQuality
-                                                       savedPathBlock:^(NSString *savedPath) {
-                                                         pathList[i] = savedPath;
-                                                       }];
+      FLTPHPickerSaveImageToPathOperation *operation = [[FLTPHPickerSaveImageToPathOperation alloc]
+               initWithResult:result
+                    maxHeight:maxHeight
+                     maxWidth:maxWidth
+          desiredImageQuality:desiredImageQuality
+                 fullMetadata:self.callContext.requestFullMetadata
+               savedPathBlock:^(NSString *savedPath) {
+                 pathList[i] = savedPath;
+               }];
       [operationQueue addOperation:operation];
     }
     [operationQueue waitUntilAllOperationsAreFinished];
diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h
index 7ba3d28..8e097072 100644
--- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h
+++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h
@@ -26,6 +26,7 @@
                      maxHeight:(NSNumber *)maxHeight
                       maxWidth:(NSNumber *)maxWidth
            desiredImageQuality:(NSNumber *)desiredImageQuality
+                  fullMetadata:(BOOL)fullMetadata
                 savedPathBlock:(void (^)(NSString *))savedPathBlock API_AVAILABLE(ios(14));
 
 @end
diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
index a81c95f..7c8fbc9 100644
--- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
+++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m
@@ -13,6 +13,7 @@
 @property(assign, nonatomic) NSNumber *maxHeight;
 @property(assign, nonatomic) NSNumber *maxWidth;
 @property(assign, nonatomic) NSNumber *desiredImageQuality;
+@property(assign, nonatomic) BOOL requestFullMetadata;
 
 @end
 
@@ -28,6 +29,7 @@
                      maxHeight:(NSNumber *)maxHeight
                       maxWidth:(NSNumber *)maxWidth
            desiredImageQuality:(NSNumber *)desiredImageQuality
+                  fullMetadata:(BOOL)fullMetadata
                 savedPathBlock:(GetSavedPath)savedPathBlock API_AVAILABLE(ios(14)) {
   if (self = [super init]) {
     if (result) {
@@ -35,6 +37,7 @@
       self.maxHeight = maxHeight;
       self.maxWidth = maxWidth;
       self.desiredImageQuality = desiredImageQuality;
+      self.requestFullMetadata = fullMetadata;
       getSavedPath = savedPathBlock;
       executing = NO;
       finished = NO;
@@ -113,7 +116,12 @@
  * Processes the image.
  */
 - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) {
-  PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result];
+  PHAsset *originalAsset;
+  // Only if requested, fetch the full "PHAsset" metadata, which requires  "Photo Library Usage"
+  // permissions.
+  if (self.requestFullMetadata) {
+    originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result];
+  }
 
   if (self.maxWidth != nil || self.maxHeight != nil) {
     localImage = [FLTImagePickerImageUtil scaledImage:localImage
diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml
index 5c30bf9..6c78b23 100755
--- a/packages/image_picker/image_picker_ios/pubspec.yaml
+++ b/packages/image_picker/image_picker_ios/pubspec.yaml
@@ -2,7 +2,7 @@
 description: iOS implementation of the image_picker plugin.
 repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker_ios
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
-version: 0.8.6
+version: 0.8.6+1
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md
index 1982a45..2952c4b 100644
--- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md
+++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md
@@ -1,6 +1,7 @@
-## NEXT
+## 0.3.2+1
 
 * Updates minimum Flutter version to 2.10.
+* Replaces deprecated ThemeData.primaryColor.
 
 ## 0.3.2
 
diff --git a/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart b/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart
index 72086ee..aa03190 100644
--- a/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart
+++ b/packages/in_app_purchase/in_app_purchase_storekit/example/lib/main.dart
@@ -336,7 +336,7 @@
         children: <Widget>[
           TextButton(
             style: TextButton.styleFrom(
-              backgroundColor: Theme.of(context).primaryColor,
+              backgroundColor: Theme.of(context).colorScheme.primary,
               // TODO(darrenaustin): Migrate to new API once it lands in stable: https://github.com/flutter/flutter/issues/105724
               // ignore: deprecated_member_use
               primary: Colors.white,
diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml
index 69bc6c6..0768371 100644
--- a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml
+++ b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml
@@ -2,7 +2,7 @@
 description: An implementation for the iOS platform of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework.
 repository: https://github.com/flutter/plugins/tree/main/packages/in_app_purchase/in_app_purchase_storekit
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22
-version: 0.3.2
+version: 0.3.2+1
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
diff --git a/packages/plugin_platform_interface/CHANGELOG.md b/packages/plugin_platform_interface/CHANGELOG.md
index 0e9b701..0b5a6b6 100644
--- a/packages/plugin_platform_interface/CHANGELOG.md
+++ b/packages/plugin_platform_interface/CHANGELOG.md
@@ -1,7 +1,11 @@
-## NEXT
+## 2.1.3
 
 * Minor fixes for new analysis options.
 * Adds additional tests for `PlatformInterface` and `MockPlatformInterfaceMixin`.
+* Modifies `PlatformInterface` to use an expando for detecting if a customer
+  tries to implement PlatformInterface using `implements` rather than `extends`.
+  This ensures that `verify` will continue to work as advertized after
+  https://github.com/dart-lang/language/issues/2020 is implemented.
 
 ## 2.1.2
 
diff --git a/packages/plugin_platform_interface/lib/plugin_platform_interface.dart b/packages/plugin_platform_interface/lib/plugin_platform_interface.dart
index a03c9ce..6733b29 100644
--- a/packages/plugin_platform_interface/lib/plugin_platform_interface.dart
+++ b/packages/plugin_platform_interface/lib/plugin_platform_interface.dart
@@ -44,9 +44,20 @@
   /// derived classes.
   ///
   /// @param token The same, non-`const` `Object` that will be passed to `verify`.
-  PlatformInterface({required Object token}) : _instanceToken = token;
+  PlatformInterface({required Object token}) {
+    _instanceTokens[this] = token;
+  }
 
-  final Object? _instanceToken;
+  /// Expando mapping instances of PlatformInterface to their associated tokens.
+  /// The reason this is not simply a private field of type `Object?` is because
+  /// as of the implementation of field promotion in Dart
+  /// (https://github.com/dart-lang/language/issues/2020), it is a runtime error
+  /// to invoke a private member that is mocked in another library.  The expando
+  /// approach prevents [_verify] from triggering this runtime exception when
+  /// encountering an implementation that uses `implements` rather than
+  /// `extends`.  This in turn allows [_verify] to throw an [AssertionError] (as
+  /// documented).
+  static final Expando<Object> _instanceTokens = Expando<Object>();
 
   /// Ensures that the platform instance was constructed with a non-`const` token
   /// that matches the provided token and throws [AssertionError] if not.
@@ -89,10 +100,10 @@
       return;
     }
     if (preventConstObject &&
-        identical(instance._instanceToken, const Object())) {
+        identical(_instanceTokens[instance], const Object())) {
       throw AssertionError('`const Object()` cannot be used as the token.');
     }
-    if (!identical(token, instance._instanceToken)) {
+    if (!identical(token, _instanceTokens[instance])) {
       throw AssertionError(
           'Platform interfaces must not be implemented with `implements`');
     }
diff --git a/packages/plugin_platform_interface/pubspec.yaml b/packages/plugin_platform_interface/pubspec.yaml
index f4800d4..6a4bc48 100644
--- a/packages/plugin_platform_interface/pubspec.yaml
+++ b/packages/plugin_platform_interface/pubspec.yaml
@@ -15,7 +15,7 @@
 # be done when absolutely necessary and after the ecosystem has already migrated to 2.X.Y version
 # that is forward compatible with 3.0.0 (ideally the ecosystem have migrated to depend on:
 # `plugin_platform_interface: >=2.X.Y <4.0.0`).
-version: 2.1.2
+version: 2.1.3
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
diff --git a/packages/plugin_platform_interface/test/plugin_platform_interface_test.dart b/packages/plugin_platform_interface/test/plugin_platform_interface_test.dart
index 329cecb..869017c 100644
--- a/packages/plugin_platform_interface/test/plugin_platform_interface_test.dart
+++ b/packages/plugin_platform_interface/test/plugin_platform_interface_test.dart
@@ -21,6 +21,12 @@
 class ImplementsSamplePluginPlatform extends Mock
     implements SamplePluginPlatform {}
 
+class ImplementsSamplePluginPlatformUsingNoSuchMethod
+    implements SamplePluginPlatform {
+  @override
+  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
 class ImplementsSamplePluginPlatformUsingMockPlatformInterfaceMixin extends Mock
     with MockPlatformInterfaceMixin
     implements SamplePluginPlatform {}
@@ -98,6 +104,13 @@
       }, throwsA(isA<AssertionError>()));
     });
 
+    test('prevents implmentation with `implements` and `noSuchMethod`', () {
+      expect(() {
+        SamplePluginPlatform.instance =
+            ImplementsSamplePluginPlatformUsingNoSuchMethod();
+      }, throwsA(isA<AssertionError>()));
+    });
+
     test('allows mocking with `implements`', () {
       final SamplePluginPlatform mock =
           ImplementsSamplePluginPlatformUsingMockPlatformInterfaceMixin();