diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/ColorProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/ColorProxyAPITests.swift new file mode 100644 index 00000000000..d59ca01e167 --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/ColorProxyAPITests.swift @@ -0,0 +1,19 @@ +// 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 UIKit +import XCTest + +@testable import webview_flutter_wkwebview + +class ColorProxyAPITests: XCTestCase { + func testPigeonDefaultConstructor() { + let registrar = TestProxyApiRegistrar() + let api = registrar.apiDelegate.pigeonApiUIColor(registrar) + + let instance = try? api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) + XCTAssertNotNil(instance) + } +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/UIViewProxyAPITests.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/UIViewProxyAPITests.swift index cbcbf3e2bd3..6ef33cb20ea 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/UIViewProxyAPITests.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/Tests/UIViewProxyAPITests.swift @@ -17,14 +17,13 @@ class UIViewProxyAPITests: XCTestCase { let api = registrar.apiDelegate.pigeonApiUIView(registrar) let instance = UIView(frame: .zero) - let value = 0xFFF4_4336 + let red = 0.5 + let green = 0.5 + let blue = 0.5 + let alpha = 0.5 try? api.pigeonDelegate.setBackgroundColor( - pigeonApi: api, pigeonInstance: instance, value: Int64(value)) - - let red = CGFloat(Double((value >> 16 & 0xff)) / 255.0) - let green = CGFloat(Double(value >> 8 & 0xff) / 255.0) - let blue = CGFloat(Double(value & 0xff) / 255.0) - let alpha = CGFloat(Double(value >> 24 & 0xff) / 255.0) + pigeonApi: api, pigeonInstance: instance, + value: UIColor(red: red, green: green, blue: blue, alpha: alpha)) XCTAssertEqual( instance.backgroundColor, UIColor(red: red, green: green, blue: blue, alpha: alpha)) diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ColorProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ColorProxyAPIDelegate.swift new file mode 100644 index 00000000000..cc6ad0ae9da --- /dev/null +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/ColorProxyAPIDelegate.swift @@ -0,0 +1,18 @@ +// 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 UIKit + +/// ProxyApi implementation for `UIColor`. +/// +/// 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 ColorProxyAPIDelegate: PigeonApiDelegateUIColor { + func pigeonDefaultConstructor( + pigeonApi: PigeonApiUIColor, red: Double, green: Double, blue: Double, alpha: Double + ) throws -> UIColor { + return UIColor(red: red, green: green, blue: blue, alpha: alpha) + } +} 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 131c8ffde7a..1d0dc38fac2 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 @@ -301,4 +302,8 @@ class ProxyAPIDelegate: WebKitLibraryPigeonProxyApiDelegate { return PigeonApiSecCertificate( pigeonRegistrar: registrar, delegate: SecCertificateProxyAPIDelegate()) } + + func pigeonApiUIColor(_ registrar: WebKitLibraryPigeonProxyApiRegistrar) -> PigeonApiUIColor { + return PigeonApiUIColor(pigeonRegistrar: registrar, delegate: ColorProxyAPIDelegate()) + } } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/UIViewProxyAPIDelegate.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/UIViewProxyAPIDelegate.swift index 9d13a816ac3..1299756e57f 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/UIViewProxyAPIDelegate.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/UIViewProxyAPIDelegate.swift @@ -12,19 +12,10 @@ /// or handle method calls on the associated native class or an instance of that class. class UIViewProxyAPIDelegate: PigeonApiDelegateUIView { #if os(iOS) - func setBackgroundColor(pigeonApi: PigeonApiUIView, pigeonInstance: UIView, value: Int64?) + func setBackgroundColor(pigeonApi: PigeonApiUIView, pigeonInstance: UIView, value: UIColor?) throws { - if value == nil { - pigeonInstance.backgroundColor = nil - } else { - let red = CGFloat(Double((value! >> 16 & 0xff)) / 255.0) - let green = CGFloat(Double(value! >> 8 & 0xff) / 255.0) - let blue = CGFloat(Double(value! & 0xff) / 255.0) - let alpha = CGFloat(Double(value! >> 24 & 0xff) / 255.0) - - pigeonInstance.backgroundColor = UIColor(red: red, green: green, blue: blue, alpha: alpha) - } + pigeonInstance.backgroundColor = value } func setOpaque(pigeonApi: PigeonApiUIView, pigeonInstance: UIView, opaque: Bool) throws { diff --git a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift index d0bea7528c0..0cff3513940 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift +++ b/packages/webview_flutter/webview_flutter_wkwebview/darwin/webview_flutter_wkwebview/Sources/webview_flutter_wkwebview/WebKitLibrary.g.swift @@ -514,6 +514,9 @@ protocol WebKitLibraryPigeonProxyApiDelegate { /// `SecCertificate` to the Dart `InstanceManager` and make calls to Dart. func pigeonApiSecCertificate(_ registrar: WebKitLibraryPigeonProxyApiRegistrar) -> PigeonApiSecCertificate + /// An implementation of [PigeonApiUIColor] used to add a new Dart instance of + /// `UIColor` to the Dart `InstanceManager` and make calls to Dart. + func pigeonApiUIColor(_ registrar: WebKitLibraryPigeonProxyApiRegistrar) -> PigeonApiUIColor } extension WebKitLibraryPigeonProxyApiDelegate { @@ -619,6 +622,8 @@ open class WebKitLibraryPigeonProxyApiRegistrar { binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiSecTrust(self)) PigeonApiSecCertificate.setUpMessageHandlers( binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiSecCertificate(self)) + PigeonApiUIColor.setUpMessageHandlers( + binaryMessenger: binaryMessenger, api: apiDelegate.pigeonApiUIColor(self)) } func tearDown() { WebKitLibraryPigeonInstanceManagerApi.setUpMessageHandlers( @@ -651,6 +656,7 @@ open class WebKitLibraryPigeonProxyApiRegistrar { PigeonApiWKWebpagePreferences.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) PigeonApiSecTrust.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) PigeonApiSecCertificate.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) + PigeonApiUIColor.setUpMessageHandlers(binaryMessenger: binaryMessenger, api: nil) } } private class WebKitLibraryPigeonInternalProxyApiCodecReaderWriter: FlutterStandardReaderWriter { @@ -1095,6 +1101,19 @@ private class WebKitLibraryPigeonInternalProxyApiCodecReaderWriter: FlutterStand return } + #if !os(macOS) + if let instance = value as? UIColor { + pigeonRegistrar.apiDelegate.pigeonApiUIColor(pigeonRegistrar).pigeonNewInstance( + pigeonInstance: instance + ) { _ in } + super.writeByte(128) + super.writeValue( + pigeonRegistrar.instanceManager.identifierWithStrongReference( + forInstance: instance as AnyObject)!) + return + } + #endif + if let instance = value as? NSObject { pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar).pigeonNewInstance( pigeonInstance: instance @@ -2895,7 +2914,7 @@ final class PigeonApiWKWebsiteDataStore: PigeonApiProtocolWKWebsiteDataStore { protocol PigeonApiDelegateUIView { #if !os(macOS) /// The view’s background color. - func setBackgroundColor(pigeonApi: PigeonApiUIView, pigeonInstance: UIView, value: Int64?) + func setBackgroundColor(pigeonApi: PigeonApiUIView, pigeonInstance: UIView, value: UIColor?) throws #endif #if !os(macOS) @@ -2934,7 +2953,7 @@ final class PigeonApiUIView: PigeonApiProtocolUIView { setBackgroundColorChannel.setMessageHandler { message, reply in let args = message as! [Any?] let pigeonInstanceArg = args[0] as! UIView - let valueArg: Int64? = nilOrValue(args[1]) + let valueArg: UIColor? = nilOrValue(args[1]) do { try api.pigeonDelegate.setBackgroundColor( pigeonApi: api, pigeonInstance: pigeonInstanceArg, value: valueArg) @@ -7701,3 +7720,107 @@ final class PigeonApiSecCertificate: PigeonApiProtocolSecCertificate { } } } +protocol PigeonApiDelegateUIColor { + #if !os(macOS) + /// Creates a color object using the specified opacity and RGB component + /// values. + /// + /// The colors are specified in an extended color space, and the input value + /// is never clamped. + func pigeonDefaultConstructor( + pigeonApi: PigeonApiUIColor, red: Double, green: Double, blue: Double, alpha: Double + ) throws -> UIColor + #endif +} + +protocol PigeonApiProtocolUIColor { +} + +final class PigeonApiUIColor: PigeonApiProtocolUIColor { + unowned let pigeonRegistrar: WebKitLibraryPigeonProxyApiRegistrar + let pigeonDelegate: PigeonApiDelegateUIColor + ///An implementation of [NSObject] used to access callback methods + var pigeonApiNSObject: PigeonApiNSObject { + return pigeonRegistrar.apiDelegate.pigeonApiNSObject(pigeonRegistrar) + } + + init(pigeonRegistrar: WebKitLibraryPigeonProxyApiRegistrar, delegate: PigeonApiDelegateUIColor) { + self.pigeonRegistrar = pigeonRegistrar + self.pigeonDelegate = delegate + } + static func setUpMessageHandlers(binaryMessenger: FlutterBinaryMessenger, api: PigeonApiUIColor?) + { + let codec: FlutterStandardMessageCodec = + api != nil + ? FlutterStandardMessageCodec( + readerWriter: WebKitLibraryPigeonInternalProxyApiCodecReaderWriter( + pigeonRegistrar: api!.pigeonRegistrar)) + : FlutterStandardMessageCodec.sharedInstance() + #if !os(macOS) + let pigeonDefaultConstructorChannel = FlutterBasicMessageChannel( + name: "dev.flutter.pigeon.webview_flutter_wkwebview.UIColor.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 + let redArg = args[1] as! Double + let greenArg = args[2] as! Double + let blueArg = args[3] as! Double + let alphaArg = args[4] as! Double + do { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + try api.pigeonDelegate.pigeonDefaultConstructor( + pigeonApi: api, red: redArg, green: greenArg, blue: blueArg, alpha: alphaArg), + withIdentifier: pigeonIdentifierArg) + reply(wrapResult(nil)) + } catch { + reply(wrapError(error)) + } + } + } else { + pigeonDefaultConstructorChannel.setMessageHandler(nil) + } + #endif + } + + #if !os(macOS) + ///Creates a Dart instance of UIColor and attaches it to [pigeonInstance]. + func pigeonNewInstance( + pigeonInstance: UIColor, 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.webview_flutter_wkwebview.UIColor.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(())) + } + } + } + } + #endif +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj index 4755950f7c8..f7a90972807 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/Runner.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 33C8DADB2E8D711500A9B7CA /* TemporaryObjCStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 33C8DADA2E8D711500A9B7CA /* TemporaryObjCStub.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; + 8F0E23522EEB5D6B002AB342 /* ColorProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0E23512EEB5D6B002AB342 /* ColorProxyAPITests.swift */; }; 8F0EDFD32E1F4967001938E6 /* ProxyAPIRegistrarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F0EDFD22E1F4967001938E6 /* ProxyAPIRegistrarTests.swift */; }; 8F1488E22D2DE27000191744 /* ScriptMessageHandlerProxyAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F1488D02D2DE27000191744 /* ScriptMessageHandlerProxyAPITests.swift */; }; 8F1488E32D2DE27000191744 /* TestProxyApiRegistrar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F1488D62D2DE27000191744 /* TestProxyApiRegistrar.swift */; }; @@ -102,6 +103,7 @@ 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 = ""; }; + 8F0E23512EEB5D6B002AB342 /* ColorProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ColorProxyAPITests.swift; path = ../../darwin/Tests/ColorProxyAPITests.swift; sourceTree = SOURCE_ROOT; }; 8F0EDFD22E1F4967001938E6 /* ProxyAPIRegistrarTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ProxyAPIRegistrarTests.swift; path = ../../darwin/Tests/ProxyAPIRegistrarTests.swift; sourceTree = SOURCE_ROOT; }; 8F1488C52D2DE27000191744 /* ErrorProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ErrorProxyAPITests.swift; path = ../../darwin/Tests/ErrorProxyAPITests.swift; sourceTree = SOURCE_ROOT; }; 8F1488C62D2DE27000191744 /* FrameInfoProxyAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FrameInfoProxyAPITests.swift; path = ../../darwin/Tests/FrameInfoProxyAPITests.swift; sourceTree = SOURCE_ROOT; }; @@ -183,6 +185,7 @@ 68BDCAEA23C3F7CB00D9C032 /* RunnerTests */ = { isa = PBXGroup; children = ( + 8F0E23512EEB5D6B002AB342 /* ColorProxyAPITests.swift */, 33C8DAD92E8D711500A9B7CA /* TemporaryObjCStub.h */, 33C8DADA2E8D711500A9B7CA /* TemporaryObjCStub.m */, 8F0EDFD22E1F4967001938E6 /* ProxyAPIRegistrarTests.swift */, @@ -562,6 +565,7 @@ 8F1488E22D2DE27000191744 /* ScriptMessageHandlerProxyAPITests.swift in Sources */, 8F1488E32D2DE27000191744 /* TestProxyApiRegistrar.swift in Sources */, 8F1488E42D2DE27000191744 /* URLRequestProxyAPITests.swift in Sources */, + 8F0E23522EEB5D6B002AB342 /* ColorProxyAPITests.swift in Sources */, 8F1488E52D2DE27000191744 /* TestBinaryMessenger.swift in Sources */, 8F1488E62D2DE27000191744 /* WebViewProxyAPITests.swift in Sources */, 8F1488E72D2DE27000191744 /* HTTPCookieStoreProxyAPITests.swift in Sources */, diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/platform_webview.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/platform_webview.dart index 8d22a2661a5..8e45601242d 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/platform_webview.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/platform_webview.dart @@ -324,7 +324,7 @@ class PlatformWebView { } /// The view’s background color. - Future setBackgroundColor(int? value) { + Future setBackgroundColor(UIColor? value) { final WKWebView webView = nativeWebView; switch (webView) { case UIViewWKWebView(): diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart index 82dd5a93f8e..ac16da6b0f4 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/common/web_kit.g.dart @@ -299,6 +299,22 @@ class PigeonOverrides { })? uRLCredential_withUser; + /// Overrides [UIColor.new]. + static UIColor Function({ + required double red, + required double green, + required double blue, + required double alpha, + void Function( + NSObject pigeon_instance, + String? keyPath, + NSObject? object, + Map? change, + )? + observeValue, + })? + uIColor_new; + /// Overrides [WKWebsiteDataStore.defaultDataStore]. static WKWebsiteDataStore? wKWebsiteDataStore_defaultDataStore; @@ -366,6 +382,7 @@ class PigeonOverrides { secTrust_getTrustResult = null; secTrust_copyCertificateChain = null; secCertificate_copyData = null; + uIColor_new = null; } } @@ -580,6 +597,9 @@ class PigeonInstanceManager { SecCertificate.pigeon_setUpMessageHandlers( pigeon_instanceManager: instanceManager, ); + UIColor.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager, + ); return instanceManager; } @@ -3394,7 +3414,7 @@ class UIView extends NSObject { } /// The view’s background color. - Future setBackgroundColor(int? value) async { + Future setBackgroundColor(UIColor? value) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _pigeonVar_codecUIView; final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; @@ -9980,3 +10000,171 @@ class SecCertificate extends NSObject { ); } } + +/// An object that stores color data and sometimes opacity. +/// +/// See https://developer.apple.com/documentation/uikit/uicolor. +class UIColor extends NSObject { + /// Creates a color object using the specified opacity and RGB component + /// values. + /// + /// The colors are specified in an extended color space, and the input value + /// is never clamped. + factory UIColor({ + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + void Function( + NSObject pigeon_instance, + String? keyPath, + NSObject? object, + Map? change, + )? + observeValue, + required double red, + required double green, + required double blue, + required double alpha, + }) { + if (PigeonOverrides.uIColor_new != null) { + return PigeonOverrides.uIColor_new!( + observeValue: observeValue, + red: red, + green: green, + blue: blue, + alpha: alpha, + ); + } + return UIColor.pigeon_new( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + observeValue: observeValue, + red: red, + green: green, + blue: blue, + alpha: alpha, + ); + } + + /// Creates a color object using the specified opacity and RGB component + /// values. + /// + /// The colors are specified in an extended color space, and the input value + /// is never clamped. + @protected + UIColor.pigeon_new({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + super.observeValue, + required double red, + required double green, + required double blue, + required double alpha, + }) : super.pigeon_detached() { + final int pigeonVar_instanceIdentifier = pigeon_instanceManager + .addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecUIColor; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const pigeonVar_channelName = + 'dev.flutter.pigeon.webview_flutter_wkwebview.UIColor.pigeon_defaultConstructor'; + final pigeonVar_channel = BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [pigeonVar_instanceIdentifier, red, green, blue, alpha], + ); + () 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 [UIColor] 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 + UIColor.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + super.observeValue, + }) : super.pigeon_detached(); + + late final _PigeonInternalProxyApiBaseCodec _pigeonVar_codecUIColor = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + UIColor Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance, + ); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final pigeonVar_channel = BasicMessageChannel( + 'dev.flutter.pigeon.webview_flutter_wkwebview.UIColor.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.webview_flutter_wkwebview.UIColor.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.webview_flutter_wkwebview.UIColor.pigeon_newInstance was null, expected non-null int.', + ); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + UIColor.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 + UIColor pigeon_copy() { + return UIColor.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + observeValue: observeValue, + ); + } +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart index 26e343b6f67..1f0a505e1df 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/legacy/web_kit_webview_widget.dart @@ -240,12 +240,27 @@ class WebKitWebViewPlatformController extends WebViewPlatformController { unawaited(updateSettings(params.webSettings!)); } - if (params.backgroundColor != null) { + if (params.backgroundColor case final Color backgroundColor) { unawaited(webView.setOpaque(false)); - unawaited(webView.setBackgroundColor(Colors.transparent.toARGB32())); + const Color transparent = Colors.transparent; + unawaited( + webView.setBackgroundColor( + UIColor( + red: transparent.r, + green: transparent.g, + blue: transparent.b, + alpha: transparent.a, + ), + ), + ); unawaited( webView.scrollView.setBackgroundColor( - params.backgroundColor?.toARGB32(), + UIColor( + red: backgroundColor.r, + green: backgroundColor.g, + blue: backgroundColor.b, + alpha: backgroundColor.a, + ), ), ); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 6eda612ef31..0cd01723f14 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -622,11 +622,21 @@ class WebKitWebViewController extends PlatformWebViewController { @override Future setBackgroundColor(Color color) { + const Color transparent = Colors.transparent; return Future.wait(>[ _webView.setOpaque(false), - _webView.setBackgroundColor(Colors.transparent.toARGB32()), + _webView.setBackgroundColor( + UIColor( + red: transparent.r, + green: transparent.g, + blue: transparent.b, + alpha: transparent.a, + ), + ), // This method must be called last. - _webView.scrollView.setBackgroundColor(color.toARGB32()), + _webView.scrollView.setBackgroundColor( + UIColor(red: color.r, green: color.g, blue: color.b, alpha: color.a), + ), ]); } diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart index 51b6e680a32..d63a87f31cb 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/pigeons/web_kit.dart @@ -602,10 +602,7 @@ abstract class WKWebsiteDataStore extends NSObject { ) abstract class UIView extends NSObject { /// The view’s background color. - // TODO(bparrishMines): Using an int here is lossy, and should be replaced - // with a full color representation. See - // https://github.com/flutter/flutter/issues/178870. - void setBackgroundColor(int? value); + void setBackgroundColor(UIColor? value); /// A Boolean value that determines whether the view is opaque. void setOpaque(bool opaque); @@ -1261,3 +1258,18 @@ abstract class SecCertificate extends NSObject { @static Uint8List copyData(SecCertificate certificate); } + +/// An object that stores color data and sometimes opacity. +/// +/// See https://developer.apple.com/documentation/uikit/uicolor. +@ProxyApi( + swiftOptions: SwiftProxyApiOptions(import: 'UIKit', supportsMacos: false), +) +abstract class UIColor extends NSObject { + /// Creates a color object using the specified opacity and RGB component + /// values. + /// + /// The colors are specified in an extended color space, and the input value + /// is never clamped. + UIColor(double red, double green, double blue, double alpha); +} diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart index 3bc0b5261bb..3f0b7bbc483 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.dart @@ -38,6 +38,14 @@ import 'web_kit_webview_widget_test.mocks.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); + setUp(() { + PigeonOverrides.pigeon_reset(); + }); + + tearDown(() { + debugDefaultTargetPlatformOverride = null; + }); + group('WebKitWebViewWidget', () { _WebViewMocks configureMocks() { final mocks = _WebViewMocks( @@ -216,6 +224,31 @@ void main() { debugDefaultTargetPlatformOverride = TargetPlatform.iOS; + final transparentUiColor = UIColor.pigeon_detached(); + final redUiColor = UIColor.pigeon_detached(); + PigeonOverrides.uIColor_new = + ({ + required double red, + required double green, + required double blue, + required double alpha, + dynamic observeValue, + }) { + if (red == Colors.transparent.r && + green == Colors.transparent.g && + blue == Colors.transparent.b && + alpha == Colors.transparent.a) { + return transparentUiColor; + } else if (red == Colors.red.r && + green == Colors.red.g && + blue == Colors.red.b && + alpha == Colors.red.a) { + return redUiColor; + } + + return UIColor.pigeon_detached(); + }; + await buildWidget( tester, mocks, @@ -229,8 +262,8 @@ void main() { ); verify(mocks.webView.setOpaque(false)); - verify(mocks.webView.setBackgroundColor(Colors.transparent.toARGB32())); - verify(mocks.scrollView.setBackgroundColor(Colors.red.toARGB32())); + verify(mocks.webView.setBackgroundColor(transparentUiColor)); + verify(mocks.scrollView.setBackgroundColor(redUiColor)); debugDefaultTargetPlatformOverride = null; }); @@ -500,7 +533,7 @@ void main() { await testController.loadFile('/path/to/file.html'); verify(mocks.webView.loadFileUrl('/path/to/file.html', '/path/to')); }); - // + testWidgets('loadFlutterAsset', (WidgetTester tester) async { final _WebViewMocks mocks = configureMocks(); final WebKitWebViewPlatformController testController = diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart index c230dfacf48..a9b111ea90a 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/legacy/web_kit_webview_widget_test.mocks.dart @@ -256,7 +256,7 @@ class MockUIScrollView extends _i1.Mock implements _i2.UIScrollView { as _i2.UIScrollView); @override - _i4.Future setBackgroundColor(int? value) => + _i4.Future setBackgroundColor(_i2.UIColor? value) => (super.noSuchMethod( Invocation.method(#setBackgroundColor, [value]), returnValue: _i4.Future.value(), @@ -976,7 +976,7 @@ class MockUIViewWKWebView extends _i1.Mock implements _i2.UIViewWKWebView { as _i2.UIViewWKWebView); @override - _i4.Future setBackgroundColor(int? value) => + _i4.Future setBackgroundColor(_i2.UIColor? value) => (super.noSuchMethod( Invocation.method(#setBackgroundColor, [value]), returnValue: _i4.Future.value(), diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index 579e84a2233..adff333fbf3 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -793,7 +793,6 @@ void main() { test('setBackgroundColor', () async { final mockWebView = MockUIViewWKWebView(); - //when(mockWebView) final mockScrollView = MockUIScrollView(); final WebKitWebViewController controller = createControllerWithMocks( @@ -801,6 +800,31 @@ void main() { mockScrollView: mockScrollView, ); + final transparentUiColor = UIColor.pigeon_detached(); + final redUiColor = UIColor.pigeon_detached(); + PigeonOverrides.uIColor_new = + ({ + required double red, + required double green, + required double blue, + required double alpha, + dynamic observeValue, + }) { + if (red == Colors.transparent.r && + green == Colors.transparent.g && + blue == Colors.transparent.b && + alpha == Colors.transparent.a) { + return transparentUiColor; + } else if (red == Colors.red.r && + green == Colors.red.g && + blue == Colors.red.b && + alpha == Colors.red.a) { + return redUiColor; + } + + return UIColor.pigeon_detached(); + }; + debugDefaultTargetPlatformOverride = TargetPlatform.iOS; await controller.setBackgroundColor(Colors.red); @@ -808,8 +832,8 @@ void main() { // UIScrollView.setBackgroundColor must be called last. verifyInOrder([ mockWebView.setOpaque(false), - mockWebView.setBackgroundColor(Colors.transparent.toARGB32()), - mockScrollView.setBackgroundColor(Colors.red.toARGB32()), + mockWebView.setBackgroundColor(transparentUiColor), + mockScrollView.setBackgroundColor(redUiColor), ]); debugDefaultTargetPlatformOverride = null; diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart index 54a4cd6fe77..080a26b3265 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.mocks.dart @@ -245,7 +245,7 @@ class MockUIScrollView extends _i1.Mock implements _i2.UIScrollView { as _i2.UIScrollView); @override - _i3.Future setBackgroundColor(int? value) => + _i3.Future setBackgroundColor(_i2.UIColor? value) => (super.noSuchMethod( Invocation.method(#setBackgroundColor, [value]), returnValue: _i3.Future.value(), @@ -1480,7 +1480,7 @@ class MockUIViewWKWebView extends _i1.Mock implements _i2.UIViewWKWebView { as _i2.UIViewWKWebView); @override - _i3.Future setBackgroundColor(int? value) => + _i3.Future setBackgroundColor(_i2.UIColor? value) => (super.noSuchMethod( Invocation.method(#setBackgroundColor, [value]), returnValue: _i3.Future.value(),