From 955249f65507aa229496d713a387152dbdb2a13b Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 14 Aug 2025 21:41:29 -0700 Subject: [PATCH 01/19] [camera_avfoundation] Replace deprecated AVCaptureVideoOrientation --- .../ios/Flutter/AppFrameworkInfo.plist | 2 +- .../camera_avfoundation/example/ios/Podfile | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 41 ++++--------------- .../xcshareddata/xcschemes/Runner.xcscheme | 2 + 4 files changed, 13 insertions(+), 34 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/Flutter/AppFrameworkInfo.plist b/packages/camera/camera_avfoundation/example/ios/Flutter/AppFrameworkInfo.plist index b3aaa733dfb..1f6b98f117b 100644 --- a/packages/camera/camera_avfoundation/example/ios/Flutter/AppFrameworkInfo.plist +++ b/packages/camera/camera_avfoundation/example/ios/Flutter/AppFrameworkInfo.plist @@ -25,6 +25,6 @@ arm64 MinimumOSVersion - 12.0 + 13.0 diff --git a/packages/camera/camera_avfoundation/example/ios/Podfile b/packages/camera/camera_avfoundation/example/ios/Podfile index bcdae34190c..f64f36010b7 100644 --- a/packages/camera/camera_avfoundation/example/ios/Podfile +++ b/packages/camera/camera_avfoundation/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +# platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index a0bc25c8cdc..b15eeb1610a 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 60; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -95,6 +95,7 @@ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 4A191381C3593DF1AC4E7559 /* 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 = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; @@ -258,6 +259,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -340,8 +342,6 @@ 03BB766E2665316900CE5A93 /* PBXTargetDependency */, ); name = RunnerTests; - packageProductDependencies = ( - ); productName = camera_exampleTests; productReference = 03BB76682665316900CE5A93 /* RunnerTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; @@ -357,7 +357,6 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - 2B62C73988DE02487EF557D4 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -401,7 +400,7 @@ ); mainGroup = 97C146E51CF9000F007C117D; packageReferences = ( - 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage" */, + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; @@ -435,28 +434,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 2B62C73988DE02487EF557D4 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/camera_avfoundation/camera_avfoundation_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/path_provider_foundation/path_provider_foundation_privacy.bundle", - "${PODS_CONFIGURATION_BUILD_DIR}/video_player_avfoundation/video_player_avfoundation_privacy.bundle", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/camera_avfoundation_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/path_provider_foundation_privacy.bundle", - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/video_player_avfoundation_privacy.bundle", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -643,7 +620,7 @@ CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = RunnerTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -676,7 +653,7 @@ CODE_SIGN_STYLE = Automatic; GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = RunnerTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -740,7 +717,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -790,7 +767,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -879,7 +856,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/camera/camera_avfoundation/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index ba0c5508103..82957b8b24a 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/camera/camera_avfoundation/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"> Date: Thu, 14 Aug 2025 21:42:03 -0700 Subject: [PATCH 02/19] remove deprecations --- .../FLTCamSetDeviceOrientationTests.swift | 60 ++++++++++--------- .../Mocks/MockCaptureConnection.swift | 13 ++++ .../camera_avfoundation/DefaultCamera.swift | 10 +++- .../Sources/camera_avfoundation_objc/FLTCam.m | 34 ++++++++++- .../FLTCaptureConnection.m | 12 ++++ .../FLTCaptureConnection.h | 12 +++- 6 files changed, 104 insertions(+), 37 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamSetDeviceOrientationTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamSetDeviceOrientationTests.swift index d7fbb505b7e..00b242a17c0 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamSetDeviceOrientationTests.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamSetDeviceOrientationTests.swift @@ -19,6 +19,7 @@ final class FLTCamSetDeviceOrientationTests: XCTestCase { let mockCapturePhotoOutput = MockCapturePhotoOutput() let mockPhotoCaptureConnection = MockCaptureConnection() mockPhotoCaptureConnection.isVideoOrientationSupported = true + mockPhotoCaptureConnection.isVideoRotationAngleSupported = true mockCapturePhotoOutput.connectionWithMediaTypeStub = { _ in mockPhotoCaptureConnection } camera.capturePhotoOutput = mockCapturePhotoOutput @@ -26,6 +27,7 @@ final class FLTCamSetDeviceOrientationTests: XCTestCase { let mockCaptureVideoDataOutput = MockCaptureVideoDataOutput() let mockVideoCaptureConnection = MockCaptureConnection() mockVideoCaptureConnection.isVideoOrientationSupported = true + mockVideoCaptureConnection.isVideoRotationAngleSupported = true mockCaptureVideoDataOutput.connectionWithMediaTypeStub = { _ in mockVideoCaptureConnection } camera.captureVideoOutput = mockCaptureVideoDataOutput @@ -35,50 +37,50 @@ final class FLTCamSetDeviceOrientationTests: XCTestCase { func testSetDeviceOrientation_setsOrientationsOfCaptureConnections() { let (camera, mockPhotoCaptureConnection, mockVideoCaptureConnection) = createCamera() - var photoSetVideoOrientationCalled = false - mockPhotoCaptureConnection.setVideoOrientationStub = { orientation in + + let photoSetVideoOrientationExpectation = expectation(description: "photo setVideoRotationAngle called") + mockPhotoCaptureConnection.setVideoRotationAngleStub = { orientation in // Device orientation is flipped compared to video orientation. When UIDeviceOrientation // is landscape left the video orientation should be landscape right. - XCTAssertEqual(orientation, .landscapeRight) - photoSetVideoOrientationCalled = true + XCTAssertEqual(orientation, 180) + photoSetVideoOrientationExpectation.fulfill() } - - var videoSetVideoOrientationCalled = false - mockVideoCaptureConnection.setVideoOrientationStub = { orientation in + + let videoSetVideoOrientationExpectation = expectation(description: "video setVideoRotationAngle called") + mockVideoCaptureConnection.setVideoRotationAngleStub = { orientation in // Device orientation is flipped compared to video orientation. When UIDeviceOrientation // is landscape left the video orientation should be landscape right. - XCTAssertEqual(orientation, .landscapeRight) - videoSetVideoOrientationCalled = true + XCTAssertEqual(orientation, 180) + videoSetVideoOrientationExpectation.fulfill() } camera.deviceOrientation = .landscapeLeft - - XCTAssertTrue(photoSetVideoOrientationCalled) - XCTAssertTrue(videoSetVideoOrientationCalled) + + waitForExpectations(timeout: 30, handler: nil) } func testSetDeviceOrientation_setsLockedOrientationsOfCaptureConnection_ifCaptureOrientationIsLocked() { let (camera, mockPhotoCaptureConnection, mockVideoCaptureConnection) = createCamera() - var photoSetVideoOrientationCalled = false - mockPhotoCaptureConnection.setVideoOrientationStub = { orientation in - XCTAssertEqual(orientation, .portraitUpsideDown) - photoSetVideoOrientationCalled = true + let photoSetVideoOrientationExpectation = expectation(description: "photo setVideoRotationAngle called") + photoSetVideoOrientationExpectation.expectedFulfillmentCount = 2 + mockPhotoCaptureConnection.setVideoRotationAngleStub = { orientation in + XCTAssertEqual(orientation, 270) + photoSetVideoOrientationExpectation.fulfill() } - - var videoSetVideoOrientationCalled = false - mockVideoCaptureConnection.setVideoOrientationStub = { orientation in - XCTAssertEqual(orientation, .portraitUpsideDown) - videoSetVideoOrientationCalled = true + + let videoSetVideoOrientationExpectation = expectation(description: "video setVideoRotationAngle called") + videoSetVideoOrientationExpectation.expectedFulfillmentCount = 2 + mockVideoCaptureConnection.setVideoRotationAngleStub = { orientation in + XCTAssertEqual(orientation, 270) + videoSetVideoOrientationExpectation.fulfill() } - camera.lockCaptureOrientation(FCPPlatformDeviceOrientation.portraitDown) camera.deviceOrientation = .landscapeLeft - - XCTAssertTrue(photoSetVideoOrientationCalled) - XCTAssertTrue(videoSetVideoOrientationCalled) + + waitForExpectations(timeout: 30, handler: nil) } func testSetDeviceOrientation_doesNotSetOrientations_ifRecordingIsInProgress() { @@ -86,8 +88,8 @@ final class FLTCamSetDeviceOrientationTests: XCTestCase { camera.startVideoRecording(completion: { _ in }, messengerForStreaming: nil) - mockPhotoCaptureConnection.setVideoOrientationStub = { _ in XCTFail() } - mockVideoCaptureConnection.setVideoOrientationStub = { _ in XCTFail() } + mockPhotoCaptureConnection.setVideoRotationAngleStub = { _ in XCTFail() } + mockVideoCaptureConnection.setVideoRotationAngleStub = { _ in XCTFail() } camera.deviceOrientation = .landscapeLeft } @@ -95,12 +97,12 @@ final class FLTCamSetDeviceOrientationTests: XCTestCase { func testSetDeviceOrientation_doesNotSetOrientations_forDuplicateUpdates() { let (camera, mockPhotoCaptureConnection, mockVideoCaptureConnection) = createCamera() var photoSetVideoOrientationCallCount = 0 - mockPhotoCaptureConnection.setVideoOrientationStub = { _ in + mockPhotoCaptureConnection.setVideoRotationAngleStub = { _ in photoSetVideoOrientationCallCount += 1 } var videoSetVideoOrientationCallCount = 0 - mockVideoCaptureConnection.setVideoOrientationStub = { _ in + mockVideoCaptureConnection.setVideoRotationAngleStub = { _ in videoSetVideoOrientationCallCount += 1 } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureConnection.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureConnection.swift index a700364818b..3e2747ebc1d 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureConnection.swift +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureConnection.swift @@ -12,6 +12,7 @@ import camera_avfoundation /// A mock implementation of `FLTCaptureConnection` that allows injecting a custom implementation. final class MockCaptureConnection: NSObject, FLTCaptureConnection { var setVideoOrientationStub: ((AVCaptureVideoOrientation) -> Void)? + var setVideoRotationAngleStub: ((CGFloat) -> Void)? var connection: AVCaptureConnection { preconditionFailure("Attempted to access unimplemented property: connection") @@ -23,7 +24,19 @@ final class MockCaptureConnection: NSObject, FLTCaptureConnection { setVideoOrientationStub?(newValue) } } + + var videoRotationAngle: CGFloat { + get { 90 } + set { + setVideoRotationAngleStub?(newValue) + } + } var inputPorts: [AVCaptureInput.Port] = [] var isVideoMirroringSupported = false var isVideoOrientationSupported = false + var isVideoRotationAngleSupported = false + + func isVideoRotationAngleSupported(_ videoRotationAngle: CGFloat) -> Bool { + isVideoRotationAngleSupported + } } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/DefaultCamera.swift b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/DefaultCamera.swift index 022ceb2367e..43905e578fb 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/DefaultCamera.swift +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/DefaultCamera.swift @@ -777,8 +777,14 @@ final class DefaultCamera: FLTCam, Camera { } // Keep the same orientation the old connections had. - if let oldConnection = oldConnection, newConnection.isVideoOrientationSupported { - newConnection.videoOrientation = oldConnection.videoOrientation + if #available(iOS 17.0, macos 14.0, *) { + if let oldConnection = oldConnection, newConnection.isVideoRotationAngleSupported(oldConnection.videoRotationAngle) { + newConnection.videoRotationAngle = oldConnection.videoRotationAngle + } + } else { + if let oldConnection = oldConnection, newConnection.isVideoOrientationSupported { + newConnection.videoOrientation = oldConnection.videoOrientation + } } // Add the new connections to the session. diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCam.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCam.m index 62c5eae2829..39ca9f21ba7 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCam.m @@ -185,13 +185,20 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation NSObject *connection = [captureOutput connectionWithMediaType:AVMediaTypeVideo]; - if (connection && connection.isVideoOrientationSupported) { - connection.videoOrientation = [self getVideoOrientationForDeviceOrientation:orientation]; + if (@available(iOS 17.0, macos 14.0, *)) { + CGFloat videoRotationAngle = [self getVideoRotationAngleForDeviceOrientation:orientation]; + if (connection && [connection isVideoRotationAngleSupported:videoRotationAngle]) { + connection.videoRotationAngle = videoRotationAngle; + } + } else { + if (connection && connection.isVideoOrientationSupported) { + connection.videoOrientation = [self getVideoOrientationForDeviceOrientation:orientation]; + } } } - (AVCaptureVideoOrientation)getVideoOrientationForDeviceOrientation: - (UIDeviceOrientation)deviceOrientation { + (UIDeviceOrientation)deviceOrientation API_DEPRECATED("Use getVideoRotationAngleForDeviceOrientation instead", macos(10.7, 14.0), ios(4.0, 17.0)) { if (deviceOrientation == UIDeviceOrientationPortrait) { return AVCaptureVideoOrientationPortrait; } else if (deviceOrientation == UIDeviceOrientationLandscapeLeft) { @@ -209,6 +216,27 @@ - (AVCaptureVideoOrientation)getVideoOrientationForDeviceOrientation: } } +- (CGFloat)getVideoRotationAngleForDeviceOrientation: +(UIDeviceOrientation)deviceOrientation API_AVAILABLE(macos(14.0), ios(17.0)) { + switch (deviceOrientation) { + case UIDeviceOrientationPortrait: + return 90; + case UIDeviceOrientationLandscapeLeft: + // Note: device orientation is flipped compared to video orientation. When UIDeviceOrientation + // is landscape left the video orientation should be landscape right. + return 180; + case UIDeviceOrientationLandscapeRight: + // Note: device orientation is flipped compared to video orientation. When UIDeviceOrientation + // is landscape right the video orientation should be landscape left. + return 0; + case UIDeviceOrientationPortraitUpsideDown: + return 270; + default: + // Default to UIDeviceOrientationPortrait. + return 90; + } +} + - (BOOL)setCaptureSessionPreset:(FCPPlatformResolutionPreset)resolutionPreset withError:(NSError **)error { switch (resolutionPreset) { diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCaptureConnection.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCaptureConnection.m index c6e1a4a3fa5..edf8de92ff7 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCaptureConnection.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/FLTCaptureConnection.m @@ -26,6 +26,10 @@ - (BOOL)isVideoOrientationSupported { return self.connection.isVideoOrientationSupported; } +- (BOOL)isVideoRotationAngleSupported:(CGFloat)videoRotationAngle { + return [self.connection isVideoRotationAngleSupported:videoRotationAngle]; +} + - (void)setVideoMirrored:(BOOL)videoMirrored { self.connection.videoMirrored = videoMirrored; } @@ -38,10 +42,18 @@ - (void)setVideoOrientation:(AVCaptureVideoOrientation)videoOrientation { self.connection.videoOrientation = videoOrientation; } +- (void)setVideoRotationAngle:(CGFloat)videoRotationAngle { + self.connection.videoRotationAngle = videoRotationAngle; +} + - (AVCaptureVideoOrientation)videoOrientation { return self.connection.videoOrientation; } +- (AVCaptureVideoOrientation)videoRotationAngle { + return self.connection.videoRotationAngle; +} + - (NSArray *)inputPorts { return self.connection.inputPorts; } diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCaptureConnection.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCaptureConnection.h index a0de806f10e..33fb8cba6be 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCaptureConnection.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation_objc/include/camera_avfoundation/FLTCaptureConnection.h @@ -14,16 +14,22 @@ NS_ASSUME_NONNULL_BEGIN @property(nonatomic, getter=isVideoMirrored) BOOL videoMirrored; /// Corresponds to the `videoOrientation` property of `AVCaptureConnection` -@property(nonatomic) AVCaptureVideoOrientation videoOrientation; +@property(nonatomic) AVCaptureVideoOrientation videoOrientation API_DEPRECATED("Use -videoRotationAngle instead", macos(10.7, 14.0), ios(4.0, 17.0)); + +/// Corresponds to the `videoRotationAngle` property of `AVCaptureConnection` +@property(nonatomic) CGFloat videoRotationAngle API_AVAILABLE(macos(14.0), ios(17.0)); /// Corresponds to the `inputPorts` property of `AVCaptureConnection` @property(nonatomic, readonly) NSArray *inputPorts; /// Corresponds to the `supportsVideoMirroring` property of `AVCaptureConnection` -@property(nonatomic, readonly, getter=isVideoMirroringSupported) BOOL supportsVideoMirroring; +@property(nonatomic, readonly, getter=isVideoMirroringSupported) BOOL supportsVideoMirroring API_DEPRECATED("Use -isVideoRotationAngleSupported: instead", macos(10.7, 14.0), ios(4.0, 17.0)); /// Corresponds to the `supportsVideoOrientation` property of `AVCaptureConnection` -@property(nonatomic, readonly, getter=isVideoOrientationSupported) BOOL supportsVideoOrientation; +@property(nonatomic, readonly, getter=isVideoOrientationSupported) BOOL supportsVideoOrientation API_DEPRECATED("Use -isVideoRotationAngleSupported: instead", macos(10.7, 14.0), ios(4.0, 17.0)); + +/// Corresponds to the `isVideoRotationAngleSupported:` method `AVCaptureConnection` +- (BOOL)isVideoRotationAngleSupported:(CGFloat)videoRotationAngle; @end From 18292d0b913a280b42ac4078629b9211e9adfe56 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 14 Aug 2025 10:54:55 -0700 Subject: [PATCH 03/19] [webview_flutter_wkwebview] Remove specialization of 'map' in example app to prevent a Swift warning --- .../webview_flutter/webview_flutter_wkwebview/CHANGELOG.md | 4 ++++ .../HTTPCookieProxyAPIDelegate.swift | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 4b07bc9e2b9..de4ff85c067 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Removes specialization of 'map' in example app to fix a Swift warning. + ## 3.23.0 * Adds support for `PlatformWebViewController.loadFileWithParams`. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift index 0b6fca238a4..1c65abcf704 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/HTTPCookieProxyAPIDelegate.swift @@ -14,7 +14,7 @@ class HTTPCookieProxyAPIDelegate: PigeonApiDelegateHTTPCookie { ) throws -> HTTPCookie { let registrar = pigeonApi.pigeonRegistrar as! ProxyAPIRegistrar - let keyValueTuples = try! properties.map<[(HTTPCookiePropertyKey, Any)], PigeonError> { + let keyValueTuples = try! properties.map { key, value in let newKey: HTTPCookiePropertyKey From 76d6aafbbb42968931c46e04dc43f5c8e2b40c27 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 14 Aug 2025 11:00:59 -0700 Subject: [PATCH 04/19] Not in example app --- packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index de4ff85c067..96fd6f22ad4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Removes specialization of 'map' in example app to fix a Swift warning. +* Removes specialization of 'map' to fix a Swift warning. ## 3.23.0 From 1cc17c719f34d187406d7077332aba18975b2754 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 14 Aug 2025 12:30:34 -0700 Subject: [PATCH 05/19] pubspec --- packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md | 2 +- packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 96fd6f22ad4..2c578ed4288 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,4 +1,4 @@ -## NEXT +## 3.23.1 * Removes specialization of 'map' to fix a Swift warning. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 7ba904f1a30..0973baf5469 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.23.0 +version: 3.23.1 environment: sdk: ^3.6.0 From c58f42f8d40cf1d2d4f870172c70e32e24b64b4f Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Tue, 5 Aug 2025 23:43:56 -0700 Subject: [PATCH 06/19] [image_picker] Add photo to simulator Photos app during test --- .../image_picker_ios/CHANGELOG.md | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 46 +++++++++++-------- .../example/ios/Runner/AppDelegate.m | 22 +++++++-- .../ImagePickerFromGalleryUITests.m | 9 +++- 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index de2edfd411f..87177efeb9b 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,6 +1,7 @@ ## NEXT * Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. +* Adds photo to Photos app during test to support iOS 26. ## 0.8.12+2 diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj index 34a80cc4d40..9f6500ce2be 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/image_picker/image_picker_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -15,23 +15,14 @@ 3A72BAD3FAE6E0FA9D80826B /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 35AE65F25E0B8C8214D8372B /* libPods-RunnerTests.a */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 5C9513011EC38BD300040975 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C9513001EC38BD300040975 /* GeneratedPluginRegistrant.m */; }; - 680049382280F2B9006DD6AB /* pngImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 680049352280F2B8006DD6AB /* pngImage.png */; }; - 680049392280F2B9006DD6AB /* jpgImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 680049362280F2B8006DD6AB /* jpgImage.jpg */; }; 6801C8392555D726009DAF8D /* ImagePickerFromGalleryUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6801C8382555D726009DAF8D /* ImagePickerFromGalleryUITests.m */; }; 782C2B45299ECE33008DC703 /* jpgImageWithRightOrientation.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 782C2B44299ECE33008DC703 /* jpgImageWithRightOrientation.jpg */; }; - 782C2B46299ECE33008DC703 /* jpgImageWithRightOrientation.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 782C2B44299ECE33008DC703 /* jpgImageWithRightOrientation.jpg */; }; 7865C5E12941326F0010E17F /* bmpImage.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E02941326F0010E17F /* bmpImage.bmp */; }; - 7865C5E22941326F0010E17F /* bmpImage.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E02941326F0010E17F /* bmpImage.bmp */; }; 7865C5E72941374F0010E17F /* heicImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E62941374F0010E17F /* heicImage.heic */; }; - 7865C5E82941374F0010E17F /* heicImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E62941374F0010E17F /* heicImage.heic */; }; 7865C5EA294137960010E17F /* icoImage.ico in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E9294137960010E17F /* icoImage.ico */; }; - 7865C5EB294137960010E17F /* icoImage.ico in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E9294137960010E17F /* icoImage.ico */; }; 7865C5ED294137AB0010E17F /* tiffImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5EC294137AB0010E17F /* tiffImage.tiff */; }; - 7865C5EE294137AB0010E17F /* tiffImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5EC294137AB0010E17F /* tiffImage.tiff */; }; 7865C5FC294157BC0010E17F /* icnsImage.icns in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FB294157BB0010E17F /* icnsImage.icns */; }; - 7865C5FD294157BC0010E17F /* icnsImage.icns in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FB294157BB0010E17F /* icnsImage.icns */; }; 7865C5FF294252A60010E17F /* proRawImage.dng in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FE294252A60010E17F /* proRawImage.dng */; }; - 7865C600294252A60010E17F /* proRawImage.dng in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FE294252A60010E17F /* proRawImage.dng */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 78CF8D862BC5E7070051231B /* OCMock in Frameworks */ = {isa = PBXBuildFile; productRef = 78CF8D852BC5E7070051231B /* OCMock */; }; 86430DF9272D71E9002D9D6C /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; }; @@ -44,9 +35,20 @@ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 9FC8F0E9229FA49E00C8D58F /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; }; - 9FC8F0EC229FA68500C8D58F /* gifImage.gif in Resources */ = {isa = PBXBuildFile; fileRef = 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */; }; BE6173D826A958B800D0974D /* ImagePickerFromLimitedGalleryUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = BE6173D726A958B800D0974D /* ImagePickerFromLimitedGalleryUITests.m */; }; F4F7A436CCA4BF276270A3AE /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC32F6993F4529982D9519F1 /* libPods-Runner.a */; }; + F706BF732E433163001263B9 /* jpgImageTall.jpg in Resources */ = {isa = PBXBuildFile; fileRef = F706BF722E433163001263B9 /* jpgImageTall.jpg */; }; + F706BF762E4331C4001263B9 /* pngImage.png in Resources */ = {isa = PBXBuildFile; fileRef = 680049352280F2B8006DD6AB /* pngImage.png */; }; + F706BF772E4331C4001263B9 /* jpgImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 680049362280F2B8006DD6AB /* jpgImage.jpg */; }; + F706BF782E4331C4001263B9 /* icnsImage.icns in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FB294157BB0010E17F /* icnsImage.icns */; }; + F706BF792E4331C4001263B9 /* icoImage.ico in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E9294137960010E17F /* icoImage.ico */; }; + F706BF7A2E4331C4001263B9 /* jpgImageTall.jpg in Resources */ = {isa = PBXBuildFile; fileRef = F706BF722E433163001263B9 /* jpgImageTall.jpg */; }; + F706BF7B2E4331C4001263B9 /* proRawImage.dng in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5FE294252A60010E17F /* proRawImage.dng */; }; + F706BF7C2E4331C4001263B9 /* heicImage.heic in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E62941374F0010E17F /* heicImage.heic */; }; + F706BF7D2E4331C4001263B9 /* tiffImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5EC294137AB0010E17F /* tiffImage.tiff */; }; + F706BF7E2E4331C4001263B9 /* jpgImageWithRightOrientation.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 782C2B44299ECE33008DC703 /* jpgImageWithRightOrientation.jpg */; }; + F706BF7F2E4331C4001263B9 /* webpImage.webp in Resources */ = {isa = PBXBuildFile; fileRef = 86E9A88F272747B90017E6E0 /* webpImage.webp */; }; + F706BF802E4331C4001263B9 /* bmpImage.bmp in Resources */ = {isa = PBXBuildFile; fileRef = 7865C5E02941326F0010E17F /* bmpImage.bmp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -122,6 +124,7 @@ BE6173D726A958B800D0974D /* ImagePickerFromLimitedGalleryUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImagePickerFromLimitedGalleryUITests.m; sourceTree = ""; }; DC6FCAAD4E7580C9B3C2E21D /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; EC32F6993F4529982D9519F1 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + F706BF722E433163001263B9 /* jpgImageTall.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = jpgImageTall.jpg; sourceTree = ""; }; F78AF3172342D9D7008449C7 /* ImagePickerTestImages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImagePickerTestImages.h; sourceTree = ""; }; F78AF3182342D9D7008449C7 /* ImagePickerTestImages.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImagePickerTestImages.m; sourceTree = ""; }; /* End PBXFileReference section */ @@ -177,6 +180,7 @@ 86E9A88F272747B90017E6E0 /* webpImage.webp */, 9FC8F0E8229FA49E00C8D58F /* gifImage.gif */, 680049362280F2B8006DD6AB /* jpgImage.jpg */, + F706BF722E433163001263B9 /* jpgImageTall.jpg */, 680049352280F2B8006DD6AB /* pngImage.png */, 7865C5E02941326F0010E17F /* bmpImage.bmp */, 7865C5E62941374F0010E17F /* heicImage.heic */, @@ -407,6 +411,7 @@ 86430DF9272D71E9002D9D6C /* gifImage.gif in Resources */, 7865C5FF294252A60010E17F /* proRawImage.dng in Resources */, 7865C5EA294137960010E17F /* icoImage.ico in Resources */, + F706BF732E433163001263B9 /* jpgImageTall.jpg in Resources */, 7865C5E72941374F0010E17F /* heicImage.heic in Resources */, 86E9A894272754A30017E6E0 /* webpImage.webp in Resources */, 86E9A895272769130017E6E0 /* pngImage.png in Resources */, @@ -421,16 +426,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9FC8F0EC229FA68500C8D58F /* gifImage.gif in Resources */, - 7865C5EE294137AB0010E17F /* tiffImage.tiff in Resources */, - 782C2B46299ECE33008DC703 /* jpgImageWithRightOrientation.jpg in Resources */, - 7865C5E82941374F0010E17F /* heicImage.heic in Resources */, - 7865C5FD294157BC0010E17F /* icnsImage.icns in Resources */, - 680049382280F2B9006DD6AB /* pngImage.png in Resources */, - 680049392280F2B9006DD6AB /* jpgImage.jpg in Resources */, - 7865C5EB294137960010E17F /* icoImage.ico in Resources */, - 7865C5E22941326F0010E17F /* bmpImage.bmp in Resources */, - 7865C600294252A60010E17F /* proRawImage.dng in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -439,6 +434,17 @@ buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + F706BF762E4331C4001263B9 /* pngImage.png in Resources */, + F706BF772E4331C4001263B9 /* jpgImage.jpg in Resources */, + F706BF782E4331C4001263B9 /* icnsImage.icns in Resources */, + F706BF792E4331C4001263B9 /* icoImage.ico in Resources */, + F706BF7A2E4331C4001263B9 /* jpgImageTall.jpg in Resources */, + F706BF7B2E4331C4001263B9 /* proRawImage.dng in Resources */, + F706BF7C2E4331C4001263B9 /* heicImage.heic in Resources */, + F706BF7D2E4331C4001263B9 /* tiffImage.tiff in Resources */, + F706BF7E2E4331C4001263B9 /* jpgImageWithRightOrientation.jpg in Resources */, + F706BF7F2E4331C4001263B9 /* webpImage.webp in Resources */, + F706BF802E4331C4001263B9 /* bmpImage.bmp in Resources */, 9FC8F0E9229FA49E00C8D58F /* gifImage.gif in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m index b790a0a5263..9259614b146 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m +++ b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m @@ -5,12 +5,28 @@ #include "AppDelegate.h" #include "GeneratedPluginRegistrant.h" +@import Photos; +@import os.log; + @implementation AppDelegate - (BOOL)application:(UIApplication *)application - didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - return [super application:application didFinishLaunchingWithOptions:launchOptions]; +didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + + if (@available(iOS 14, *)) { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + __block NSError *saveError = nil; + [PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelAddOnly handler:^(PHAuthorizationStatus status) { + if (![PHPhotoLibrary.sharedPhotoLibrary performChangesAndWait:^{ + NSURL *jpgImageTall = [bundle URLForResource:@"jpgImageTall" withExtension:@"jpg"]; + [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:jpgImageTall]; + } error:&saveError]) { + os_log_error(OS_LOG_DEFAULT, "%@", saveError); + } + }]; + } + return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m index 45149f65f19..c8b1987c175 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m @@ -220,7 +220,14 @@ - (void)launchPickerAndPickWithMaxWidth:(NSNumber *)maxWidth os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription); XCTFail(@"Failed due to not able to find an image with %@ seconds", @(kElementWaitingTime)); } - [aImage tap]; + if (aImage.isHittable) { + [aImage tap]; + } else { + // Know issue where tappable things are not hittable. Tap it anyway. + // See https://github.com/flutter/plugins/pull/6783 for a similar case. + XCUICoordinate *coordinate = [aImage coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; + [coordinate tap]; + } // Find the picked image. XCUIElement *pickedImage = self.app.images[@"image_picker_example_picked_image"].firstMatch; From 8f71ab7ac61d0d8dcfabce2a715d5c86ec9761a8 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Tue, 5 Aug 2025 23:58:43 -0700 Subject: [PATCH 07/19] Update packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m --- .../example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m index c8b1987c175..c4f7b7cbc25 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m @@ -223,7 +223,7 @@ - (void)launchPickerAndPickWithMaxWidth:(NSNumber *)maxWidth if (aImage.isHittable) { [aImage tap]; } else { - // Know issue where tappable things are not hittable. Tap it anyway. + // Known issue where tappable elements are not hittable. Tap it anyway. // See https://github.com/flutter/plugins/pull/6783 for a similar case. XCUICoordinate *coordinate = [aImage coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; [coordinate tap]; From c1f7b61a2fe300280eaa0637c30b924462633142 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 6 Aug 2025 00:34:16 -0700 Subject: [PATCH 08/19] Format --- .../example/ios/Runner/AppDelegate.m | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m index 9259614b146..80a6de082a3 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m +++ b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m @@ -11,22 +11,30 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application -didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [GeneratedPluginRegistrant registerWithRegistry:self]; - - if (@available(iOS 14, *)) { - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - __block NSError *saveError = nil; - [PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelAddOnly handler:^(PHAuthorizationStatus status) { - if (![PHPhotoLibrary.sharedPhotoLibrary performChangesAndWait:^{ - NSURL *jpgImageTall = [bundle URLForResource:@"jpgImageTall" withExtension:@"jpg"]; - [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:jpgImageTall]; - } error:&saveError]) { - os_log_error(OS_LOG_DEFAULT, "%@", saveError); - } - }]; - } - return [super application:application didFinishLaunchingWithOptions:launchOptions]; + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [GeneratedPluginRegistrant registerWithRegistry:self]; + + if (@available(iOS 14, *)) { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + __block NSError *saveError = nil; + [PHPhotoLibrary + requestAuthorizationForAccessLevel:PHAccessLevelAddOnly + handler:^(PHAuthorizationStatus status) { + if (![PHPhotoLibrary.sharedPhotoLibrary + performChangesAndWait:^{ + NSURL *jpgImageTall = + [bundle URLForResource:@"jpgImageTall" + withExtension:@"jpg"]; + [PHAssetChangeRequest + creationRequestForAssetFromImageAtFileURL: + jpgImageTall]; + } + error:&saveError]) { + os_log_error(OS_LOG_DEFAULT, "%@", saveError); + } + }]; + } + return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end From 048df06839ff56a4a8647056dbe44e8b5660aa31 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 6 Aug 2025 00:36:30 -0700 Subject: [PATCH 09/19] library --- packages/image_picker/image_picker_ios/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index 87177efeb9b..4a1bae0c068 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,7 +1,7 @@ ## NEXT * Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. -* Adds photo to Photos app during test to support iOS 26. +* Adds photo to Photos library during test to support iOS 26. ## 0.8.12+2 From 1be0155206cfeafb358e7007fbb171acb8054a08 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 6 Aug 2025 10:17:04 -0700 Subject: [PATCH 10/19] format --- .../ImagePickerFromGalleryUITests.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m index c4f7b7cbc25..d17f2b6b600 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromGalleryUITests.m @@ -220,14 +220,14 @@ - (void)launchPickerAndPickWithMaxWidth:(NSNumber *)maxWidth os_log_error(OS_LOG_DEFAULT, "%@", self.app.debugDescription); XCTFail(@"Failed due to not able to find an image with %@ seconds", @(kElementWaitingTime)); } - if (aImage.isHittable) { - [aImage tap]; - } else { - // Known issue where tappable elements are not hittable. Tap it anyway. - // See https://github.com/flutter/plugins/pull/6783 for a similar case. - XCUICoordinate *coordinate = [aImage coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; - [coordinate tap]; - } + if (aImage.isHittable) { + [aImage tap]; + } else { + // Known issue where tappable elements are not hittable. Tap it anyway. + // See https://github.com/flutter/plugins/pull/6783 for a similar case. + XCUICoordinate *coordinate = [aImage coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; + [coordinate tap]; + } // Find the picked image. XCUIElement *pickedImage = self.app.images[@"image_picker_example_picked_image"].firstMatch; From a3d24758893705ca716f0d3a9b2d2f95ee0f1cb0 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 13 Aug 2025 22:13:58 -0700 Subject: [PATCH 11/19] another test --- .../example/ios/Runner/AppDelegate.m | 48 +++++++++++-------- .../ImagePickerFromLimitedGalleryUITests.m | 9 +++- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m index 80a6de082a3..855192bbb2d 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m +++ b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m @@ -13,27 +13,33 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; - - if (@available(iOS 14, *)) { - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - __block NSError *saveError = nil; - [PHPhotoLibrary - requestAuthorizationForAccessLevel:PHAccessLevelAddOnly - handler:^(PHAuthorizationStatus status) { - if (![PHPhotoLibrary.sharedPhotoLibrary - performChangesAndWait:^{ - NSURL *jpgImageTall = - [bundle URLForResource:@"jpgImageTall" - withExtension:@"jpg"]; - [PHAssetChangeRequest - creationRequestForAssetFromImageAtFileURL: - jpgImageTall]; - } - error:&saveError]) { - os_log_error(OS_LOG_DEFAULT, "%@", saveError); - } - }]; - } + if (@available(iOS 14, *)) { + // Seed the photo library with at least one image for tests to operate on. + NSString *photoAddedKey = @"PhotoAdded"; + BOOL photoAdded = [NSUserDefaults.standardUserDefaults boolForKey:photoAddedKey]; + if (!photoAdded) { + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + __block NSError *saveError = nil; + [PHPhotoLibrary + requestAuthorizationForAccessLevel:PHAccessLevelAddOnly + handler:^(PHAuthorizationStatus status) { + if ([PHPhotoLibrary.sharedPhotoLibrary + performChangesAndWait:^{ + NSURL *jpgImageTall = + [bundle URLForResource:@"jpgImageTall" + withExtension:@"jpg"]; + [PHAssetChangeRequest + creationRequestForAssetFromImageAtFileURL: + jpgImageTall]; + } + error:&saveError]) { + [NSUserDefaults.standardUserDefaults setBool:YES forKey:photoAddedKey]; + } else { + os_log_error(OS_LOG_DEFAULT, "%@", saveError); + } + }]; + } + } return [super application:application didFinishLaunchingWithOptions:launchOptions]; } diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromLimitedGalleryUITests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromLimitedGalleryUITests.m index bc5f8add84f..fc246ee793d 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromLimitedGalleryUITests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerUITests/ImagePickerFromLimitedGalleryUITests.m @@ -115,7 +115,14 @@ - (void)testSelectingFromGallery API_AVAILABLE(ios(14)) { @(kLimitedElementWaitingTime)); } - [aImage tap]; + if (aImage.isHittable) { + [aImage tap]; + } else { + // Known issue where tappable elements are not hittable. Tap it anyway. + // See https://github.com/flutter/plugins/pull/6783 for a similar case. + XCUICoordinate *coordinate = [aImage coordinateWithNormalizedOffset:CGVectorMake(0, 0)]; + [coordinate tap]; + } // Find the picked image. XCUIElement *pickedImage = self.app.images[@"image_picker_example_picked_image"].firstMatch; From d6db9866633241924aac3321e539def368239a96 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 13 Aug 2025 22:27:08 -0700 Subject: [PATCH 12/19] format --- .../example/ios/Runner/AppDelegate.m | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m index 855192bbb2d..f9e336794b4 100644 --- a/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m +++ b/packages/image_picker/image_picker_ios/example/ios/Runner/AppDelegate.m @@ -13,33 +13,35 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; - if (@available(iOS 14, *)) { + if (@available(iOS 14, *)) { // Seed the photo library with at least one image for tests to operate on. NSString *photoAddedKey = @"PhotoAdded"; BOOL photoAdded = [NSUserDefaults.standardUserDefaults boolForKey:photoAddedKey]; if (!photoAdded) { - NSBundle *bundle = [NSBundle bundleForClass:[self class]]; - __block NSError *saveError = nil; - [PHPhotoLibrary - requestAuthorizationForAccessLevel:PHAccessLevelAddOnly - handler:^(PHAuthorizationStatus status) { - if ([PHPhotoLibrary.sharedPhotoLibrary - performChangesAndWait:^{ - NSURL *jpgImageTall = - [bundle URLForResource:@"jpgImageTall" - withExtension:@"jpg"]; - [PHAssetChangeRequest - creationRequestForAssetFromImageAtFileURL: - jpgImageTall]; - } - error:&saveError]) { - [NSUserDefaults.standardUserDefaults setBool:YES forKey:photoAddedKey]; - } else { - os_log_error(OS_LOG_DEFAULT, "%@", saveError); - } - }]; - } + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + __block NSError *saveError = nil; + [PHPhotoLibrary + requestAuthorizationForAccessLevel:PHAccessLevelAddOnly + handler:^(PHAuthorizationStatus status) { + if ([PHPhotoLibrary.sharedPhotoLibrary + performChangesAndWait:^{ + NSURL *jpgImageTall = + [bundle URLForResource:@"jpgImageTall" + withExtension:@"jpg"]; + [PHAssetChangeRequest + creationRequestForAssetFromImageAtFileURL: + jpgImageTall]; + } + error:&saveError]) { + [NSUserDefaults.standardUserDefaults + setBool:YES + forKey:photoAddedKey]; + } else { + os_log_error(OS_LOG_DEFAULT, "%@", saveError); + } + }]; } + } return [super application:application didFinishLaunchingWithOptions:launchOptions]; } From 8c2a04c24d4b18aefad5ac53e677d7ff11ca8cb0 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Mon, 4 Aug 2025 16:41:32 -0700 Subject: [PATCH 13/19] Xcode 26 --- .ci.yaml | 18 ++++++------------ .ci/scripts/create_simulator.sh | 2 +- .ci/targets/ios_platform_tests.yaml | 2 +- packages/pigeon/tool/shared/test_suites.dart | 4 ++-- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.ci.yaml b/.ci.yaml index 208528bffb7..244cb2d554f 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -93,12 +93,12 @@ platform_properties: [ {"dependency": "ruby", "version": "ruby_3.1-pod_1.13"} ] - os: Mac-14|Mac-15.5 + os: Mac-15 device_type: none cpu: arm64 $flutter/osx_sdk : >- { - "sdk_version": "16c5032a" + "sdk_version": "17a5285i" } mac_x64: properties: @@ -106,12 +106,12 @@ platform_properties: [ {"dependency": "ruby", "version": "ruby_3.1-pod_1.13"} ] - os: Mac-14|Mac-15.5 + os: Mac-15 device_type: none cpu: x86 $flutter/osx_sdk : >- { - "sdk_version": "16c5032a" + "sdk_version": "17a5285i" } targets: @@ -394,7 +394,7 @@ targets: ### Android tasks ### - name: Linux_android android_build_all_packages master recipe: packages/packages - timeout: 60 + timeout: 30 properties: version_file: flutter_master.version # This builds the all_packages app only in a current JDK. @@ -407,7 +407,7 @@ targets: - name: Linux_android android_build_all_packages stable recipe: packages/packages - timeout: 60 + timeout: 30 properties: add_recipes_cq: "true" version_file: flutter_stable.version @@ -1084,7 +1084,6 @@ targets: - name: Mac_arm64 macos_platform_tests stable - packages recipe: packages/packages - presubmit: false timeout: 60 properties: channel: stable @@ -1220,7 +1219,6 @@ targets: # Don't run full platform tests on both channels in pre-submit. - name: Mac_arm64 ios_platform_tests_shard_1 stable recipe: packages/packages - presubmit: false timeout: 60 properties: channel: stable @@ -1235,7 +1233,6 @@ targets: - name: Mac_arm64 ios_platform_tests_shard_2 stable recipe: packages/packages - presubmit: false timeout: 60 properties: channel: stable @@ -1250,7 +1247,6 @@ targets: - name: Mac_arm64 ios_platform_tests_shard_3 stable recipe: packages/packages - presubmit: false timeout: 60 properties: channel: stable @@ -1265,7 +1261,6 @@ targets: - name: Mac_arm64 ios_platform_tests_shard_4 stable recipe: packages/packages - presubmit: false timeout: 60 properties: channel: stable @@ -1280,7 +1275,6 @@ targets: - name: Mac_arm64 ios_platform_tests_shard_5 stable recipe: packages/packages - presubmit: false timeout: 60 properties: channel: stable diff --git a/.ci/scripts/create_simulator.sh b/.ci/scripts/create_simulator.sh index ace8261b635..ff695854ca9 100755 --- a/.ci/scripts/create_simulator.sh +++ b/.ci/scripts/create_simulator.sh @@ -9,7 +9,7 @@ set -o pipefail # The name here must match remove_simulator.sh readonly DEVICE_NAME=Flutter-iPhone readonly DEVICE=com.apple.CoreSimulator.SimDeviceType.iPhone-14 -readonly OS=com.apple.CoreSimulator.SimRuntime.iOS-18-2 +readonly OS=com.apple.CoreSimulator.SimRuntime.iOS-26-0 # Delete any existing devices named Flutter-iPhone. Having more than one may # cause issues when builds target the device. diff --git a/.ci/targets/ios_platform_tests.yaml b/.ci/targets/ios_platform_tests.yaml index a2b01241e73..81db8791c80 100644 --- a/.ci/targets/ios_platform_tests.yaml +++ b/.ci/targets/ios_platform_tests.yaml @@ -22,7 +22,7 @@ tasks: - name: native test script: .ci/scripts/tool_runner.sh # Simulator name and version must match name and version in create_simulator.sh - args: ["native-test", "--ios", "--ios-destination", "platform=iOS Simulator,name=Flutter-iPhone,OS=18.2", "--xcode-warnings-exceptions=script/configs/xcode_warnings_exceptions.yaml"] + args: ["native-test", "--ios", "--ios-destination", "platform=iOS Simulator,name=Flutter-iPhone,OS=26.0", "--xcode-warnings-exceptions=script/configs/xcode_warnings_exceptions.yaml"] - name: boot simulator # Ensure simulator is still booted script: .ci/scripts/boot_simulator.sh diff --git a/packages/pigeon/tool/shared/test_suites.dart b/packages/pigeon/tool/shared/test_suites.dart index a16afe0c2e7..bbe639ef1bc 100644 --- a/packages/pigeon/tool/shared/test_suites.dart +++ b/packages/pigeon/tool/shared/test_suites.dart @@ -327,8 +327,8 @@ Future _runIOSPluginUnitTests(String testPluginPath) async { const String deviceName = 'Pigeon-Test-iPhone'; const String deviceType = 'com.apple.CoreSimulator.SimDeviceType.iPhone-14'; - const String deviceRuntime = 'com.apple.CoreSimulator.SimRuntime.iOS-18-2'; - const String deviceOS = '18.2'; + const String deviceRuntime = 'com.apple.CoreSimulator.SimRuntime.iOS-26-0'; + const String deviceOS = '26.0'; await _createSimulator(deviceName, deviceType, deviceRuntime); return runXcodeBuild( '$examplePath/ios', From 7406fbb81a01e96548f80c4b517188abeb81701b Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 26 Jun 2025 10:21:00 -0700 Subject: [PATCH 14/19] [ci] Increase deprecation check minimum to iOS 17 --- .ci/targets/ios_platform_tests.yaml | 2 +- script/configs/exclude_xcode_deprecation.yaml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.ci/targets/ios_platform_tests.yaml b/.ci/targets/ios_platform_tests.yaml index 81db8791c80..9e21e529736 100644 --- a/.ci/targets/ios_platform_tests.yaml +++ b/.ci/targets/ios_platform_tests.yaml @@ -18,7 +18,7 @@ tasks: - name: xcode analyze deprecation # Ensure we don't accidentally introduce deprecated code. script: .ci/scripts/tool_runner.sh - args: ["xcode-analyze", "--ios", "--ios-min-version=14.0", "--exclude=script/configs/exclude_xcode_deprecation.yaml,script/configs/xcode_warnings_exceptions.yaml"] + args: ["xcode-analyze", "--ios", "--ios-min-version=17.0", "--exclude=script/configs/exclude_xcode_deprecation.yaml,script/configs/xcode_warnings_exceptions.yaml"] - name: native test script: .ci/scripts/tool_runner.sh # Simulator name and version must match name and version in create_simulator.sh diff --git a/script/configs/exclude_xcode_deprecation.yaml b/script/configs/exclude_xcode_deprecation.yaml index 416839c8e38..91cebb830d5 100644 --- a/script/configs/exclude_xcode_deprecation.yaml +++ b/script/configs/exclude_xcode_deprecation.yaml @@ -1,2 +1,4 @@ -# TODO(louisehsu): Remove deprecation check when StoreKit 2 is adopted. https://github.com/flutter/flutter/issues/116383 +# TODO(jmagman): Remove deprecation exclusion when AVCaptureVideoOrientation is migrated. https://github.com/flutter/flutter/issues/170438 +- camera_avfoundation +# TODO(jmagman): Remove when SKDownload is marked unavailable. https://github.com/flutter/flutter/issues/105490 - in_app_purchase_storekit From 63b724302c8fe94aba9549107458dea7bca69e91 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Tue, 5 Aug 2025 21:24:38 -0700 Subject: [PATCH 15/19] roll again --- .ci/targets/ios_platform_tests.yaml | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 30 ++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.ci/targets/ios_platform_tests.yaml b/.ci/targets/ios_platform_tests.yaml index 9e21e529736..81db8791c80 100644 --- a/.ci/targets/ios_platform_tests.yaml +++ b/.ci/targets/ios_platform_tests.yaml @@ -18,7 +18,7 @@ tasks: - name: xcode analyze deprecation # Ensure we don't accidentally introduce deprecated code. script: .ci/scripts/tool_runner.sh - args: ["xcode-analyze", "--ios", "--ios-min-version=17.0", "--exclude=script/configs/exclude_xcode_deprecation.yaml,script/configs/xcode_warnings_exceptions.yaml"] + args: ["xcode-analyze", "--ios", "--ios-min-version=14.0", "--exclude=script/configs/exclude_xcode_deprecation.yaml,script/configs/xcode_warnings_exceptions.yaml"] - name: native test script: .ci/scripts/tool_runner.sh # Simulator name and version must match name and version in create_simulator.sh diff --git a/packages/local_auth/local_auth_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/local_auth/local_auth_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 52fbc6fd946..c4ac8d5a2bc 100644 --- a/packages/local_auth/local_auth_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/local_auth/local_auth_darwin/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,7 +1,7 @@ + version = "1.7"> @@ -38,6 +38,34 @@ ReferencedContainer = "container:Runner.xcodeproj"> + + + + + + + + Date: Wed, 13 Aug 2025 23:28:29 -0700 Subject: [PATCH 16/19] Swift format --- .../NavigationDelegateProxyAPITests.swift | 38 ++++++++++--------- .../NavigationDelegateProxyAPIDelegate.swift | 6 ++- .../ProxyAPIRegistrar.swift | 7 ++-- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift index df77486425b..01b4aff2aea 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/NavigationDelegateProxyAPITests.swift @@ -170,11 +170,12 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { func decidePolicyForNavigationAction( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, navigationAction navigationActionArg: WKNavigationAction, - completion: @escaping ( - Result< - webview_flutter_wkwebview.NavigationActionPolicy, webview_flutter_wkwebview.PigeonError - > - ) -> Void + completion: + @escaping ( + Result< + webview_flutter_wkwebview.NavigationActionPolicy, webview_flutter_wkwebview.PigeonError + > + ) -> Void ) { decidePolicyForNavigationActionArgs = [webViewArg, navigationActionArg] completion(.success(.allow)) @@ -183,11 +184,12 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { func decidePolicyForNavigationResponse( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, navigationResponse navigationResponseArg: WKNavigationResponse, - completion: @escaping ( - Result< - webview_flutter_wkwebview.NavigationResponsePolicy, webview_flutter_wkwebview.PigeonError - > - ) -> Void + completion: + @escaping ( + Result< + webview_flutter_wkwebview.NavigationResponsePolicy, webview_flutter_wkwebview.PigeonError + > + ) -> Void ) { decidePolicyForNavigationResponseArgs = [webViewArg, navigationResponseArg] completion(.success(.cancel)) @@ -219,12 +221,13 @@ class TestNavigationDelegateApi: PigeonApiProtocolWKNavigationDelegate { func didReceiveAuthenticationChallenge( pigeonInstance pigeonInstanceArg: WKNavigationDelegate, webView webViewArg: WKWebView, challenge challengeArg: URLAuthenticationChallenge, - completion: @escaping ( - Result< - webview_flutter_wkwebview.AuthenticationChallengeResponse, - webview_flutter_wkwebview.PigeonError - > - ) -> Void + completion: + @escaping ( + Result< + webview_flutter_wkwebview.AuthenticationChallengeResponse, + webview_flutter_wkwebview.PigeonError + > + ) -> Void ) { didReceiveAuthenticationChallengeArgs = [webViewArg, challengeArg] completion( @@ -241,7 +244,8 @@ class TestWebView: WKWebView { } } -class TestURLAuthenticationChallengeSender: NSObject, URLAuthenticationChallengeSender, @unchecked +class TestURLAuthenticationChallengeSender: NSObject, URLAuthenticationChallengeSender, + @unchecked Sendable { func use(_ credential: URLCredential, for challenge: URLAuthenticationChallenge) { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift index 4988bb60228..e30d9bb74a1 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/NavigationDelegateProxyAPIDelegate.swift @@ -233,7 +233,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { #if compiler(>=6.0) public func webView( _ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping @MainActor (URLSession.AuthChallengeDisposition, URLCredential?) + completionHandler: + @escaping @MainActor (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { @@ -256,7 +257,8 @@ public class NavigationDelegateImpl: NSObject, WKNavigationDelegate { #else public func webView( _ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, - completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> + completionHandler: + @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void ) { registrar.dispatchOnMainThread { onFailure in diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift index 51de764a622..5c6257173a2 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ProxyAPIRegistrar.swift @@ -78,9 +78,10 @@ open class ProxyAPIRegistrar: WebKitLibraryPigeonProxyApiRegistrar { /// Handles calling a Flutter method on the main thread. func dispatchOnMainThread( - execute work: @escaping ( - _ onFailure: @escaping (_ methodName: String, _ error: PigeonError) -> Void - ) -> Void + execute work: + @escaping ( + _ onFailure: @escaping (_ methodName: String, _ error: PigeonError) -> Void + ) -> Void ) { DispatchQueue.main.async { work { methodName, error in From 12fd56b32bc70b0488e6f6ac6762175fcf5e716f Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 13 Aug 2025 23:38:19 -0700 Subject: [PATCH 17/19] Remove mac_x64 --- .ci.yaml | 66 -------------------------------------------------------- 1 file changed, 66 deletions(-) diff --git a/.ci.yaml b/.ci.yaml index 244cb2d554f..76c010f036e 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -100,19 +100,6 @@ platform_properties: { "sdk_version": "17a5285i" } - mac_x64: - properties: - dependencies: >- - [ - {"dependency": "ruby", "version": "ruby_3.1-pod_1.13"} - ] - os: Mac-15 - device_type: none - cpu: x86 - $flutter/osx_sdk : >- - { - "sdk_version": "17a5285i" - } targets: - name: Linux repo_checks @@ -1039,33 +1026,6 @@ targets: target_file: macos_repo_checks.yaml ### macOS desktop tasks ### - # macos-platform_tests builds all the packages on ARM, so this build is run - # on Intel to give us build coverage of both host types. - - name: Mac_x64 build_all_packages master - recipe: packages/packages - timeout: 30 - properties: - version_file: flutter_master.version - target_file: macos_build_all_packages.yaml - channel: master - env_variables: >- - { - "CHANNEL": "master" - } - - - name: Mac_x64 build_all_packages stable - recipe: packages/packages - timeout: 30 - properties: - add_recipes_cq: "true" - version_file: flutter_stable.version - target_file: macos_build_all_packages.yaml - channel: stable - env_variables: >- - { - "CHANNEL": "stable" - } - # TODO(stuartmorgan): Remove "- packages" from all task names once # flutter/plugins is merged into this repo and turned down; it's here only # because names must be unique across all flutter repositories. @@ -1119,32 +1079,6 @@ targets: } ### iOS tasks ### - # ios_platform_tests builds all the packages on ARM, so this build is run - # on Intel to give us build coverage of both host types. - - name: Mac_x64 ios_build_all_packages master - recipe: packages/packages - timeout: 30 - properties: - channel: master - version_file: flutter_master.version - target_file: ios_build_all_packages.yaml - env_variables: >- - { - "CHANNEL": "master" - } - - - name: Mac_x64 ios_build_all_packages stable - recipe: packages/packages - timeout: 30 - properties: - channel: stable - version_file: flutter_stable.version - target_file: ios_build_all_packages.yaml - env_variables: >- - { - "CHANNEL": "stable" - } - - name: Mac_arm64 ios_platform_tests_shard_1 master recipe: packages/packages timeout: 60 From 230938073b8ed92f501e5d06f4b5ff77e2da3e25 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Wed, 13 Aug 2025 23:46:53 -0700 Subject: [PATCH 18/19] Xcode beta 5 --- .ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci.yaml b/.ci.yaml index 76c010f036e..abce0f57ac7 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -98,7 +98,7 @@ platform_properties: cpu: arm64 $flutter/osx_sdk : >- { - "sdk_version": "17a5285i" + "sdk_version": "17a5295f" } targets: From 591208abe6a8a6bca5a7913dfb1bfc139b9c29e9 Mon Sep 17 00:00:00 2001 From: Jenn Magder Date: Thu, 14 Aug 2025 00:06:43 -0700 Subject: [PATCH 19/19] CHANGELOG --- packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 2c578ed4288..50cb6faa185 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,6 +1,7 @@ ## 3.23.1 * Removes specialization of 'map' to fix a Swift warning. +* Formats Swift code for Xcode 26 compatibility. ## 3.23.0