mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
2d80a248cd
Summary: Changelog: [Internal] Introduce native command `setNativeRefreshing`, it has the word Native in order to avoid name conflict with setRefreshing in Android implementation. Even this component is iOS only, it would make it easier to merge them in the future. Introduce `RCTRefreshableProtocol` and make `RCTRefreshControl` and `RCTPullToRefreshViewComponentView` to conform to the protocol so view manager can forward command to both, Paper and Fabric component. Reviewed By: mmmulani Differential Revision: D18475804 fbshipit-source-id: 4c19225784efc931b7b8f2d2671cc839bce429bf
184 lines
4.6 KiB
Plaintext
184 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 "RCTPullToRefreshViewComponentView.h"
|
|
|
|
#import <react/components/rncore/ComponentDescriptors.h>
|
|
#import <react/components/rncore/EventEmitters.h>
|
|
#import <react/components/rncore/Props.h>
|
|
#import <react/components/rncore/RCTComponentViewHelpers.h>
|
|
|
|
#import <React/RCTConversions.h>
|
|
#import <React/RCTRefreshableProtocol.h>
|
|
#import <React/RCTScrollViewComponentView.h>
|
|
|
|
using namespace facebook::react;
|
|
|
|
@interface RCTPullToRefreshViewComponentView () <RCTPullToRefreshViewViewProtocol, RCTRefreshableProtocol>
|
|
@end
|
|
|
|
@implementation RCTPullToRefreshViewComponentView {
|
|
UIRefreshControl *_refreshControl;
|
|
RCTScrollViewComponentView *_scrollViewComponentView;
|
|
}
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame
|
|
{
|
|
if (self = [super initWithFrame:frame]) {
|
|
// This view is not designed to be visible, it only serves UIViewController-like purpose managing
|
|
// attaching and detaching of a pull-to-refresh view to a scroll view.
|
|
// The pull-to-refresh view is not a subview of this view.
|
|
self.hidden = YES;
|
|
|
|
static auto const defaultProps = std::make_shared<PullToRefreshViewProps const>();
|
|
_props = defaultProps;
|
|
|
|
_refreshControl = [[UIRefreshControl alloc] init];
|
|
[_refreshControl addTarget:self
|
|
action:@selector(handleUIControlEventValueChanged)
|
|
forControlEvents:UIControlEventValueChanged];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
#pragma mark - RCTComponentViewProtocol
|
|
|
|
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
{
|
|
return concreteComponentDescriptorProvider<PullToRefreshViewComponentDescriptor>();
|
|
}
|
|
|
|
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
{
|
|
auto const &oldConcreteProps = *std::static_pointer_cast<PullToRefreshViewProps const>(_props);
|
|
auto const &newConcreteProps = *std::static_pointer_cast<PullToRefreshViewProps const>(props);
|
|
|
|
if (newConcreteProps.refreshing != oldConcreteProps.refreshing) {
|
|
if (newConcreteProps.refreshing) {
|
|
[_refreshControl beginRefreshing];
|
|
} else {
|
|
[_refreshControl endRefreshing];
|
|
}
|
|
}
|
|
|
|
BOOL needsUpdateTitle = NO;
|
|
|
|
if (newConcreteProps.title != oldConcreteProps.title) {
|
|
needsUpdateTitle = YES;
|
|
}
|
|
|
|
if (newConcreteProps.titleColor != oldConcreteProps.titleColor) {
|
|
needsUpdateTitle = YES;
|
|
}
|
|
|
|
if (needsUpdateTitle) {
|
|
[self _updateTitle];
|
|
}
|
|
|
|
[super updateProps:props oldProps:oldProps];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (void)handleUIControlEventValueChanged
|
|
{
|
|
std::static_pointer_cast<PullToRefreshViewEventEmitter const>(_eventEmitter)->onRefresh({});
|
|
}
|
|
|
|
- (void)_updateTitle
|
|
{
|
|
auto const &concreteProps = *std::static_pointer_cast<PullToRefreshViewProps const>(_props);
|
|
|
|
if (concreteProps.title.empty()) {
|
|
_refreshControl.attributedTitle = nil;
|
|
return;
|
|
}
|
|
|
|
NSMutableDictionary *attributes = [NSMutableDictionary dictionary];
|
|
if (concreteProps.titleColor) {
|
|
attributes[NSForegroundColorAttributeName] = RCTUIColorFromSharedColor(concreteProps.titleColor);
|
|
}
|
|
|
|
_refreshControl.attributedTitle =
|
|
[[NSAttributedString alloc] initWithString:RCTNSStringFromString(concreteProps.title) attributes:attributes];
|
|
}
|
|
|
|
#pragma mark - Attaching & Detaching
|
|
|
|
- (void)didMoveToWindow
|
|
{
|
|
if (self.window) {
|
|
[self _attach];
|
|
} else {
|
|
[self _detach];
|
|
}
|
|
}
|
|
|
|
- (void)_attach
|
|
{
|
|
if (_scrollViewComponentView) {
|
|
[self _detach];
|
|
}
|
|
|
|
_scrollViewComponentView = [RCTScrollViewComponentView findScrollViewComponentViewForView:self];
|
|
if (!_scrollViewComponentView) {
|
|
return;
|
|
}
|
|
|
|
if (@available(iOS 10.0, macOS 13.0, *)) {
|
|
_scrollViewComponentView.scrollView.refreshControl = _refreshControl;
|
|
}
|
|
}
|
|
|
|
- (void)_detach
|
|
{
|
|
if (!_scrollViewComponentView) {
|
|
return;
|
|
}
|
|
|
|
// iOS requires to end refreshing before unmounting.
|
|
[_refreshControl endRefreshing];
|
|
|
|
if (@available(iOS 10.0, macOS 13.0, *)) {
|
|
_scrollViewComponentView.scrollView.refreshControl = nil;
|
|
}
|
|
_scrollViewComponentView = nil;
|
|
}
|
|
|
|
#pragma mark - Native commands
|
|
|
|
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
|
{
|
|
RCTPullToRefreshViewHandleCommand(self, commandName, args);
|
|
}
|
|
|
|
- (void)setNativeRefreshing:(BOOL)refreshing
|
|
{
|
|
if (refreshing) {
|
|
[_refreshControl beginRefreshing];
|
|
} else {
|
|
[_refreshControl endRefreshing];
|
|
}
|
|
}
|
|
|
|
#pragma mark - RCTRefreshableProtocol
|
|
|
|
- (void)setRefreshing:(BOOL)refreshing
|
|
{
|
|
[self setNativeRefreshing:refreshing];
|
|
}
|
|
|
|
#pragma mark -
|
|
|
|
- (NSString *)componentViewName_DO_NOT_USE_THIS_IS_BROKEN
|
|
{
|
|
return @"RefreshControl";
|
|
}
|
|
|
|
@end
|