mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
e7c41ec5fb
Summary: Original commit changeset: a3324b5df6e6 ConcreteStateTeller is being replaced with a new built-in state autorepeat mechanism. Changelog: [Internal] Fabric-specific internal change. Reviewed By: sammy-SC Differential Revision: D25687697 fbshipit-source-id: 849bb8b6c244b17a49b5fe140346d90a9a7e52ff
155 lines
4.6 KiB
Plaintext
155 lines
4.6 KiB
Plaintext
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#import "RCTInputAccessoryComponentView.h"
|
|
|
|
#import <React/RCTBackedTextInputViewProtocol.h>
|
|
#import <React/RCTConversions.h>
|
|
#import <React/RCTSurfaceTouchHandler.h>
|
|
#import <React/RCTUtils.h>
|
|
#import <React/UIView+React.h>
|
|
#import <react/renderer/components/inputaccessory/InputAccessoryComponentDescriptor.h>
|
|
#import <react/renderer/components/rncore/Props.h>
|
|
#import "RCTInputAccessoryContentView.h"
|
|
|
|
#import "RCTFabricComponentsPlugins.h"
|
|
|
|
using namespace facebook::react;
|
|
|
|
static UIView<RCTBackedTextInputViewProtocol> *_Nullable RCTFindTextInputWithNativeId(UIView *view, NSString *nativeId)
|
|
{
|
|
if ([view respondsToSelector:@selector(inputAccessoryViewID)] &&
|
|
[view respondsToSelector:@selector(setInputAccessoryView:)]) {
|
|
UIView<RCTBackedTextInputViewProtocol> *typed = (UIView<RCTBackedTextInputViewProtocol> *)view;
|
|
if (!nativeId || [typed.inputAccessoryViewID isEqualToString:nativeId]) {
|
|
return typed;
|
|
}
|
|
}
|
|
|
|
for (UIView *subview in view.subviews) {
|
|
UIView<RCTBackedTextInputViewProtocol> *result = RCTFindTextInputWithNativeId(subview, nativeId);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
@implementation RCTInputAccessoryComponentView {
|
|
InputAccessoryShadowNode::ConcreteState::Shared _state;
|
|
RCTInputAccessoryContentView *_contentView;
|
|
RCTSurfaceTouchHandler *_touchHandler;
|
|
UIView<RCTBackedTextInputViewProtocol> __weak *_textInput;
|
|
}
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
if (self = [super initWithFrame:frame]) {
|
|
static const auto defaultProps = std::make_shared<const InputAccessoryProps>();
|
|
_props = defaultProps;
|
|
_contentView = [RCTInputAccessoryContentView new];
|
|
_touchHandler = [RCTSurfaceTouchHandler new];
|
|
[_touchHandler attachToView:_contentView];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)didMoveToWindow
|
|
{
|
|
[super didMoveToWindow];
|
|
|
|
if (self.window && !_textInput) {
|
|
if (self.nativeId) {
|
|
_textInput = RCTFindTextInputWithNativeId(self.window, self.nativeId);
|
|
_textInput.inputAccessoryView = _contentView;
|
|
} else {
|
|
_textInput = RCTFindTextInputWithNativeId(_contentView, nil);
|
|
}
|
|
|
|
if (!self.nativeId) {
|
|
[self becomeFirstResponder];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (BOOL)canBecomeFirstResponder
|
|
{
|
|
return true;
|
|
}
|
|
|
|
- (UIView *)inputAccessoryView
|
|
{
|
|
return _contentView;
|
|
}
|
|
|
|
#pragma mark - RCTComponentViewProtocol
|
|
|
|
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
{
|
|
return concreteComponentDescriptorProvider<InputAccessoryComponentDescriptor>();
|
|
}
|
|
|
|
- (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
{
|
|
[_contentView insertSubview:childComponentView atIndex:index];
|
|
}
|
|
|
|
- (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
{
|
|
[childComponentView removeFromSuperview];
|
|
}
|
|
|
|
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
{
|
|
auto const &oldInputAccessoryProps = *std::static_pointer_cast<InputAccessoryProps const>(_props);
|
|
auto const &newInputAccessoryProps = *std::static_pointer_cast<InputAccessoryProps const>(props);
|
|
|
|
if (newInputAccessoryProps.backgroundColor != oldInputAccessoryProps.backgroundColor) {
|
|
_contentView.backgroundColor = RCTUIColorFromSharedColor(newInputAccessoryProps.backgroundColor);
|
|
}
|
|
|
|
[super updateProps:props oldProps:oldProps];
|
|
self.hidden = true;
|
|
}
|
|
|
|
- (void)updateState:(const facebook::react::State::Shared &)state
|
|
oldState:(const facebook::react::State::Shared &)oldState
|
|
{
|
|
_state = std::static_pointer_cast<InputAccessoryShadowNode::ConcreteState const>(state);
|
|
CGSize oldScreenSize = RCTCGSizeFromSize(_state->getData().viewportSize);
|
|
CGSize viewportSize = RCTViewportSize();
|
|
viewportSize.height = std::nan("");
|
|
if (oldScreenSize.width != viewportSize.width) {
|
|
auto stateData = InputAccessoryState{RCTSizeFromCGSize(viewportSize)};
|
|
_state->updateState(std::move(stateData));
|
|
}
|
|
}
|
|
|
|
- (void)updateLayoutMetrics:(LayoutMetrics const &)layoutMetrics
|
|
oldLayoutMetrics:(LayoutMetrics const &)oldLayoutMetrics
|
|
{
|
|
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
|
|
[_contentView setFrame:RCTCGRectFromRect(layoutMetrics.getContentFrame())];
|
|
}
|
|
|
|
- (void)prepareForRecycle
|
|
{
|
|
[super prepareForRecycle];
|
|
_state.reset();
|
|
_textInput = nil;
|
|
}
|
|
|
|
@end
|
|
|
|
Class<RCTComponentViewProtocol> RCTInputAccessoryCls(void)
|
|
{
|
|
return RCTInputAccessoryComponentView.class;
|
|
}
|