fix(tvos): unify remote and text input ownership
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
35DB0C8FEF635A3BCA0B722A /* PackageInfoPlusPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9426EFA282CDA8E0E98EEE9 /* PackageInfoPlusPlugin.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
5C71F5F7B33075F2B007825B /* MpvPlayerPluginShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73645904F226A24585A092CE /* MpvPlayerPluginShared.swift */; };
|
||||
4F1000024F1000024F100002 /* FlutterNativeTextInputTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4F1000014F1000014F100001 /* FlutterNativeTextInputTests.mm */; };
|
||||
65AC2C222043B3E6723E2076 /* ConnectivityPlusPluginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 934BC4E316D2AC788C954766 /* ConnectivityPlusPluginTests.swift */; };
|
||||
691577F0EB3F4EB1A5160280 /* MpvPlayerCoreBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D52A3BDA46E79969EA1DF3AC /* MpvPlayerCoreBase.swift */; };
|
||||
6F3C0DD6F2F8DA14E7E2F386 /* MpvPlayerCore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A12B8610AE5D580077264851 /* MpvPlayerCore.swift */; };
|
||||
@@ -96,6 +97,7 @@
|
||||
3CCA7E80F3A99D8759F2E59F /* ConnectivityProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityProvider.swift; sourceTree = "<group>"; };
|
||||
41369A2B262AECB35079F6CC /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
420881FB6A648A2AFD39FFF2 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
4F1000014F1000014F100001 /* FlutterNativeTextInputTests.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = FlutterNativeTextInputTests.mm; sourceTree = "<group>"; };
|
||||
5E1F41676FEF1AB57076F8B9 /* DeviceInfoPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DeviceInfoPlusPlugin.swift; sourceTree = "<group>"; };
|
||||
66F56950138FF220CA079EB3 /* TvosEventDeliveryCoordinator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TvosEventDeliveryCoordinator.swift; sourceTree = "<group>"; };
|
||||
67C3193A50DFDECE2B92D075 /* ConnectivityPlusPlugin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ConnectivityPlusPlugin.swift; sourceTree = "<group>"; };
|
||||
@@ -337,6 +339,7 @@
|
||||
F9BDF6E09E3B9347861D2A50 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4F1000014F1000014F100001 /* FlutterNativeTextInputTests.mm */,
|
||||
2A7C0B1D9E5F4A6381027C11 /* MpvPlayerContractTests.swift */,
|
||||
FE6C8125B201A8BC3261AE2B /* TvosEventDeliveryCoordinatorTests.swift */,
|
||||
934BC4E316D2AC788C954766 /* ConnectivityPlusPluginTests.swift */,
|
||||
@@ -590,6 +593,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4F1000024F1000024F100002 /* FlutterNativeTextInputTests.mm in Sources */,
|
||||
2A7C0B1D9E5F4A6381027C12 /* MpvPlayerContractTests.swift in Sources */,
|
||||
D2004D7BB4A40340AB7A01E0 /* TvosEventDeliveryCoordinatorTests.swift in Sources */,
|
||||
65AC2C222043B3E6723E2076 /* ConnectivityPlusPluginTests.swift in Sources */,
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
#import <Flutter/Flutter.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface FlutterTextInputView : UIView
|
||||
@property(nonatomic, readonly) UITextField* tvosTextInputProxy;
|
||||
@end
|
||||
|
||||
@interface FlutterTextInputPlugin : NSObject
|
||||
@property(nonatomic, weak) UIViewController* viewController;
|
||||
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result;
|
||||
- (UIView<UITextInput>*)textInputView;
|
||||
@end
|
||||
|
||||
@interface FlutterEngine (NativeTextInputTests)
|
||||
- (FlutterTextInputPlugin*)textInputPlugin;
|
||||
@end
|
||||
|
||||
@interface FlutterViewController (NativeTextInputTests)
|
||||
@property(nonatomic, assign, getter=isTvosNativeTextInputActive) BOOL tvosNativeTextInputActive;
|
||||
@end
|
||||
|
||||
@interface FlutterNativeTextInputTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FlutterNativeTextInputTests {
|
||||
FlutterEngine* _engine;
|
||||
FlutterViewController* _flutterViewController;
|
||||
UIWindow* _window;
|
||||
FlutterTextInputPlugin* _textInputPlugin;
|
||||
}
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
id<UIApplicationDelegate> appDelegate = UIApplication.sharedApplication.delegate;
|
||||
_window = appDelegate.window;
|
||||
_flutterViewController = (FlutterViewController*)_window.rootViewController;
|
||||
XCTAssertTrue([_flutterViewController isKindOfClass:[FlutterViewController class]]);
|
||||
_engine = _flutterViewController.engine;
|
||||
_textInputPlugin = [_engine textInputPlugin];
|
||||
XCTAssertNotNil(_textInputPlugin);
|
||||
}
|
||||
- (void)tearDown {
|
||||
[self invokeTextInput:@"TextInput.hide" arguments:nil];
|
||||
[self invokeTextInput:@"TextInput.clearClient" arguments:nil];
|
||||
_textInputPlugin = nil;
|
||||
_engine = nil;
|
||||
_flutterViewController = nil;
|
||||
_window = nil;
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testPackagedEngineUsesRealUITextFieldProxyAndNativeSessionRouting {
|
||||
[self invokeTextInput:@"TextInput.setClient"
|
||||
arguments:@[
|
||||
@123,
|
||||
@{
|
||||
@"inputType" : @{@"name" : @"TextInputType.url"},
|
||||
@"keyboardAppearance" : @"Brightness.dark",
|
||||
@"obscureText" : @NO,
|
||||
@"inputAction" : @"TextInputAction.done",
|
||||
@"smartDashesType" : @"0",
|
||||
@"smartQuotesType" : @"0",
|
||||
@"autocorrect" : @NO,
|
||||
@"enableInteractiveSelection" : @YES,
|
||||
},
|
||||
]];
|
||||
[self invokeTextInput:@"TextInput.setEditingState"
|
||||
arguments:@{
|
||||
@"text" : @"plezy.local",
|
||||
@"selectionBase" : @2,
|
||||
@"selectionExtent" : @7,
|
||||
@"selectionAffinity" : @"TextAffinity.downstream",
|
||||
@"composingBase" : @(-1),
|
||||
@"composingExtent" : @(-1),
|
||||
}];
|
||||
|
||||
FlutterTextInputView* inputView = (FlutterTextInputView*)[_textInputPlugin textInputView];
|
||||
UITextField* proxy = inputView.tvosTextInputProxy;
|
||||
XCTAssertNotNil(proxy);
|
||||
XCTAssertEqualObjects(proxy.text, @"plezy.local");
|
||||
XCTAssertEqual(proxy.keyboardType, UIKeyboardTypeURL);
|
||||
XCTAssertEqual(proxy.returnKeyType, UIReturnKeyDone);
|
||||
XCTAssertEqual(proxy.autocorrectionType, UITextAutocorrectionTypeNo);
|
||||
XCTAssertEqual([proxy offsetFromPosition:proxy.beginningOfDocument toPosition:proxy.selectedTextRange.start], 2);
|
||||
XCTAssertEqual([proxy offsetFromPosition:proxy.beginningOfDocument toPosition:proxy.selectedTextRange.end], 7);
|
||||
|
||||
[self invokeTextInput:@"TextInput.show" arguments:nil];
|
||||
[self waitForMainRunLoop];
|
||||
XCTAssertTrue(proxy.isFirstResponder);
|
||||
XCTAssertTrue(_flutterViewController.tvosNativeTextInputActive);
|
||||
|
||||
[self invokeTextInput:@"TextInput.hide" arguments:nil];
|
||||
[self waitForMainRunLoop];
|
||||
XCTAssertFalse(proxy.isFirstResponder);
|
||||
XCTAssertFalse(_flutterViewController.tvosNativeTextInputActive);
|
||||
}
|
||||
|
||||
- (void)invokeTextInput:(NSString*)method arguments:(id)arguments {
|
||||
FlutterMethodCall* call = [FlutterMethodCall methodCallWithMethodName:method arguments:arguments];
|
||||
[_textInputPlugin handleMethodCall:call
|
||||
result:^(id result){
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)waitForMainRunLoop {
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"main run loop"];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[expectation fulfill];
|
||||
});
|
||||
[self waitForExpectations:@[ expectation ] timeout:2];
|
||||
}
|
||||
|
||||
@end
|
||||
+1
-1
@@ -1 +1 @@
|
||||
278584b13cf4def805f9ceaa97ee4e318d5e5f75c9222286295135e5691d23ef
|
||||
21dcdb1b8e369e8385cd41b7844e7248923680a22f4ea303a976494724a0829d
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3.44.0+4
|
||||
3.44.0+5
|
||||
|
||||
Reference in New Issue
Block a user