Support image props for Slider component, feature parity with pre-Fabric Slider
Summary: The biggest change is that (1) the image proxy/observer code from the Image component has been generalized, (2) the four image props for the Slider component are fully supported, (3) a handful of props that were ignored or buggy on iOS now perform as expected. Reviewed By: shergin Differential Revision: D13954892 fbshipit-source-id: bec8ad3407c39a1cb186d9541a73b509dccc92ce
This commit is contained in:
Родитель
7f646a5b68
Коммит
b6318acbab
|
@ -5,20 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <React/RCTViewComponentView.h>
|
||||
#import "RCTViewComponentView.h"
|
||||
#import <React/RCTImageResponseDelegate.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol RCTImageResponseDelegate <NSObject>
|
||||
|
||||
- (void)didReceiveImage:(UIImage *)image fromObserver:(void*)observer;
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void*)observer;
|
||||
- (void)didReceiveFailureFromObserver:(void*)observer;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* UIView class for root <Image> component.
|
||||
*/
|
||||
|
|
|
@ -12,49 +12,17 @@
|
|||
#import <react/components/image/ImageProps.h>
|
||||
#import <react/components/image/ImageShadowNode.h>
|
||||
#import <react/imagemanager/ImageRequest.h>
|
||||
#import <react/imagemanager/ImageResponse.h>
|
||||
#import <react/imagemanager/ImageResponseObserver.h>
|
||||
#import <react/imagemanager/RCTImagePrimitivesConversions.h>
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
|
||||
#import "RCTConversions.h"
|
||||
#import "MainQueueExecutor.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
class ImageResponseObserverProxy: public ImageResponseObserver {
|
||||
public:
|
||||
ImageResponseObserverProxy(void* delegate): delegate_((__bridge id<RCTImageResponseDelegate>)delegate) {}
|
||||
|
||||
void didReceiveImage(const ImageResponse &imageResponse) override {
|
||||
UIImage *image = (__bridge UIImage *)imageResponse.getImage().get();
|
||||
void *this_ = this;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[delegate_ didReceiveImage:image fromObserver:this_];
|
||||
});
|
||||
}
|
||||
|
||||
void didReceiveProgress (float p) override {
|
||||
void *this_ = this;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[delegate_ didReceiveProgress:p fromObserver:this_];
|
||||
});
|
||||
}
|
||||
void didReceiveFailure() override {
|
||||
void *this_ = this;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[delegate_ didReceiveFailureFromObserver:this_];
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
id<RCTImageResponseDelegate> delegate_;
|
||||
};
|
||||
|
||||
@implementation RCTImageComponentView {
|
||||
UIImageView *_imageView;
|
||||
SharedImageLocalData _imageLocalData;
|
||||
std::shared_ptr<const ImageResponseObserverCoordinator> _coordinator;
|
||||
std::unique_ptr<ImageResponseObserverProxy> _imageResponseObserverProxy;
|
||||
std::unique_ptr<RCTImageResponseObserverProxy> _imageResponseObserverProxy;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
|
@ -68,7 +36,7 @@ private:
|
|||
|
||||
_imageView.contentMode = (UIViewContentMode)RCTResizeModeFromImageResizeMode(defaultProps->resizeMode);
|
||||
|
||||
_imageResponseObserverProxy = std::make_unique<ImageResponseObserverProxy>((__bridge void *)self);
|
||||
_imageResponseObserverProxy = std::make_unique<RCTImageResponseObserverProxy>((__bridge void *)self);
|
||||
|
||||
self.contentView = _imageView;
|
||||
}
|
||||
|
@ -110,12 +78,18 @@ private:
|
|||
- (void)updateLocalData:(SharedLocalData)localData
|
||||
oldLocalData:(SharedLocalData)oldLocalData
|
||||
{
|
||||
SharedImageLocalData previousData = _imageLocalData;
|
||||
_imageLocalData = std::static_pointer_cast<const ImageLocalData>(localData);
|
||||
assert(_imageLocalData);
|
||||
self.coordinator = _imageLocalData->getImageRequest().getObserverCoordinator();
|
||||
bool havePreviousData = previousData != nullptr;
|
||||
|
||||
// Loading actually starts a little before this
|
||||
std::static_pointer_cast<const ImageEventEmitter>(_eventEmitter)->onLoadStart();
|
||||
if (!havePreviousData || _imageLocalData->getImageSource() != previousData->getImageSource()) {
|
||||
self.coordinator = _imageLocalData->getImageRequest().getObserverCoordinator();
|
||||
|
||||
// Loading actually starts a little before this, but this is the first time we know
|
||||
// the image is loading and can fire an event from this component
|
||||
std::static_pointer_cast<const ImageEventEmitter>(_eventEmitter)->onLoadStart();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setCoordinator:(std::shared_ptr<const ImageResponseObserverCoordinator>)coordinator {
|
||||
|
|
|
@ -10,12 +10,31 @@
|
|||
#import <react/components/slider/SliderEventEmitter.h>
|
||||
#import <react/components/slider/SliderProps.h>
|
||||
#import <react/components/slider/SliderShadowNode.h>
|
||||
#import <react/components/slider/SliderLocalData.h>
|
||||
#import <React/RCTImageResponseObserverProxy.h>
|
||||
|
||||
#import "MainQueueExecutor.h"
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
@implementation RCTSliderComponentView {
|
||||
UISlider *_sliderView;
|
||||
float _prevValue;
|
||||
float _previousValue;
|
||||
SharedSliderLocalData _sliderLocalData;
|
||||
|
||||
UIImage *_trackImage;
|
||||
UIImage *_minimumTrackImage;
|
||||
UIImage *_maximumTrackImage;
|
||||
UIImage *_thumbImage;
|
||||
|
||||
std::shared_ptr<const ImageResponseObserverCoordinator> _trackImageCoordinator;
|
||||
std::unique_ptr<RCTImageResponseObserverProxy> _trackImageResponseObserverProxy;
|
||||
std::shared_ptr<const ImageResponseObserverCoordinator> _minimumTrackImageCoordinator;
|
||||
std::unique_ptr<RCTImageResponseObserverProxy> _minimumTrackImageResponseObserverProxy;
|
||||
std::shared_ptr<const ImageResponseObserverCoordinator> _maximumTrackImageCoordinator;
|
||||
std::unique_ptr<RCTImageResponseObserverProxy> _maximumTrackImageResponseObserverProxy;
|
||||
std::shared_ptr<const ImageResponseObserverCoordinator> _thumbImageCoordinator;
|
||||
std::unique_ptr<RCTImageResponseObserverProxy> _thumbImageResponseObserverProxy;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame
|
||||
|
@ -29,9 +48,19 @@ using namespace facebook::react;
|
|||
[_sliderView addTarget:self
|
||||
action:@selector(onChange:)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
[_sliderView addTarget:self
|
||||
action:@selector(sliderTouchEnd:)
|
||||
forControlEvents:(UIControlEventTouchUpInside |
|
||||
UIControlEventTouchUpOutside |
|
||||
UIControlEventTouchCancel)];
|
||||
|
||||
_sliderView.value = defaultProps->value;
|
||||
|
||||
_trackImageResponseObserverProxy = std::make_unique<RCTImageResponseObserverProxy>((__bridge void *)self);
|
||||
_minimumTrackImageResponseObserverProxy = std::make_unique<RCTImageResponseObserverProxy>((__bridge void *)self);
|
||||
_maximumTrackImageResponseObserverProxy = std::make_unique<RCTImageResponseObserverProxy>((__bridge void *)self);
|
||||
_thumbImageResponseObserverProxy = std::make_unique<RCTImageResponseObserverProxy>((__bridge void *)self);
|
||||
|
||||
self.contentView = _sliderView;
|
||||
}
|
||||
|
||||
|
@ -55,7 +84,17 @@ using namespace facebook::react;
|
|||
// `value`
|
||||
if (oldSliderProps.value != newSliderProps.value) {
|
||||
_sliderView.value = newSliderProps.value;
|
||||
_prevValue = newSliderProps.value;
|
||||
_previousValue = newSliderProps.value;
|
||||
}
|
||||
|
||||
// `minimumValue`
|
||||
if (oldSliderProps.minimumValue != newSliderProps.minimumValue) {
|
||||
_sliderView.minimumValue = newSliderProps.minimumValue;
|
||||
}
|
||||
|
||||
// `maximumValue`
|
||||
if (oldSliderProps.maximumValue != newSliderProps.maximumValue) {
|
||||
_sliderView.maximumValue = newSliderProps.maximumValue;
|
||||
}
|
||||
|
||||
// `disabled`
|
||||
|
@ -79,14 +118,178 @@ using namespace facebook::react;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)onChange:(UISlider *)sender
|
||||
- (void)updateLocalData:(SharedLocalData)localData
|
||||
oldLocalData:(SharedLocalData)oldLocalData
|
||||
{
|
||||
if (_prevValue == sender.value) {
|
||||
return;
|
||||
}
|
||||
_prevValue = sender.value;
|
||||
SharedSliderLocalData previousData = _sliderLocalData;
|
||||
_sliderLocalData = std::static_pointer_cast<const SliderLocalData>(localData);
|
||||
assert(_sliderLocalData);
|
||||
bool havePreviousData = previousData != nullptr;
|
||||
|
||||
std::dynamic_pointer_cast<const SliderEventEmitter>(_eventEmitter)->onValueChange(sender.value);
|
||||
if (!havePreviousData || _sliderLocalData->getTrackImageSource() != previousData->getTrackImageSource()) {
|
||||
self.trackImageCoordinator = _sliderLocalData->getTrackImageRequest().getObserverCoordinator();
|
||||
}
|
||||
if (!havePreviousData || _sliderLocalData->getMinimumTrackImageSource() != previousData->getMinimumTrackImageSource()) {
|
||||
self.minimumTrackImageCoordinator = _sliderLocalData->getMinimumTrackImageRequest().getObserverCoordinator();
|
||||
}
|
||||
if (!havePreviousData || _sliderLocalData->getMaximumTrackImageSource() != previousData->getMaximumTrackImageSource()) {
|
||||
self.maximumTrackImageCoordinator = _sliderLocalData->getMaximumTrackImageRequest().getObserverCoordinator();
|
||||
}
|
||||
if (!havePreviousData || _sliderLocalData->getThumbImageSource() != previousData->getThumbImageSource()) {
|
||||
self.thumbImageCoordinator = _sliderLocalData->getThumbImageRequest().getObserverCoordinator();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTrackImageCoordinator:(std::shared_ptr<const ImageResponseObserverCoordinator>)coordinator {
|
||||
if (_trackImageCoordinator) {
|
||||
_trackImageCoordinator->removeObserver(_trackImageResponseObserverProxy.get());
|
||||
}
|
||||
_trackImageCoordinator = coordinator;
|
||||
if (_trackImageCoordinator != nullptr) {
|
||||
_trackImageCoordinator->addObserver(_trackImageResponseObserverProxy.get());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMinimumTrackImageCoordinator:(std::shared_ptr<const ImageResponseObserverCoordinator>)coordinator {
|
||||
if (_minimumTrackImageCoordinator) {
|
||||
_minimumTrackImageCoordinator->removeObserver(_minimumTrackImageResponseObserverProxy.get());
|
||||
}
|
||||
_minimumTrackImageCoordinator = coordinator;
|
||||
if (_minimumTrackImageCoordinator != nullptr) {
|
||||
_minimumTrackImageCoordinator->addObserver(_minimumTrackImageResponseObserverProxy.get());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setMaximumTrackImageCoordinator:(std::shared_ptr<const ImageResponseObserverCoordinator>)coordinator {
|
||||
if (_maximumTrackImageCoordinator) {
|
||||
_maximumTrackImageCoordinator->removeObserver(_maximumTrackImageResponseObserverProxy.get());
|
||||
}
|
||||
_maximumTrackImageCoordinator = coordinator;
|
||||
if (_maximumTrackImageCoordinator != nullptr) {
|
||||
_maximumTrackImageCoordinator->addObserver(_maximumTrackImageResponseObserverProxy.get());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setThumbImageCoordinator:(std::shared_ptr<const ImageResponseObserverCoordinator>)coordinator {
|
||||
if (_thumbImageCoordinator) {
|
||||
_thumbImageCoordinator->removeObserver(_thumbImageResponseObserverProxy.get());
|
||||
}
|
||||
_thumbImageCoordinator = coordinator;
|
||||
if (_thumbImageCoordinator != nullptr) {
|
||||
_thumbImageCoordinator->addObserver(_thumbImageResponseObserverProxy.get());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setTrackImage:(UIImage *)trackImage {
|
||||
if ([trackImage isEqual:_trackImage]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_trackImage = trackImage;
|
||||
_minimumTrackImage = nil;
|
||||
_maximumTrackImage = nil;
|
||||
CGFloat width = trackImage.size.width / 2;
|
||||
UIImage *minimumTrackImage = [trackImage resizableImageWithCapInsets:(UIEdgeInsets){
|
||||
0, width, 0, width
|
||||
} resizingMode:UIImageResizingModeStretch];
|
||||
UIImage *maximumTrackImage = [trackImage resizableImageWithCapInsets:(UIEdgeInsets){
|
||||
0, width, 0, width
|
||||
} resizingMode:UIImageResizingModeStretch];
|
||||
[_sliderView setMinimumTrackImage:minimumTrackImage forState:UIControlStateNormal];
|
||||
[_sliderView setMaximumTrackImage:maximumTrackImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
-(void)setMinimumTrackImage:(UIImage *)minimumTrackImage {
|
||||
if ([minimumTrackImage isEqual:_minimumTrackImage] && _trackImage == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
_trackImage = nil;
|
||||
_minimumTrackImage = minimumTrackImage;
|
||||
_minimumTrackImage = [_minimumTrackImage resizableImageWithCapInsets:(UIEdgeInsets) {
|
||||
0, _minimumTrackImage.size.width, 0, 0
|
||||
} resizingMode:UIImageResizingModeStretch];
|
||||
[_sliderView setMinimumTrackImage:_minimumTrackImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
-(void)setMaximumTrackImage:(UIImage *)maximumTrackImage {
|
||||
if ([maximumTrackImage isEqual:_maximumTrackImage] && _trackImage == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
_trackImage = nil;
|
||||
_maximumTrackImage = maximumTrackImage;
|
||||
_maximumTrackImage = [_maximumTrackImage resizableImageWithCapInsets:(UIEdgeInsets) {
|
||||
0, 0, 0, _maximumTrackImage.size.width
|
||||
} resizingMode:UIImageResizingModeStretch];
|
||||
[_sliderView setMaximumTrackImage:_maximumTrackImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
-(void)setThumbImage:(UIImage *)thumbImage {
|
||||
if ([thumbImage isEqual:_thumbImage]) {
|
||||
return;
|
||||
}
|
||||
|
||||
_thumbImage = thumbImage;
|
||||
[_sliderView setThumbImage:thumbImage forState:UIControlStateNormal];
|
||||
}
|
||||
|
||||
- (void)onChange:(UISlider *)sender
|
||||
{
|
||||
[self onChange:sender withContinuous:YES];
|
||||
}
|
||||
|
||||
- (void)sliderTouchEnd:(UISlider *)sender
|
||||
{
|
||||
[self onChange:sender withContinuous:NO];
|
||||
}
|
||||
|
||||
- (void)onChange:(UISlider *)sender withContinuous:(BOOL)continuous
|
||||
{
|
||||
float value = sender.value;
|
||||
|
||||
const auto &props = *std::static_pointer_cast<const SliderProps>(_props);
|
||||
|
||||
if (props.step > 0 && value <= (props.maximumValue - props.minimumValue)) {
|
||||
value = MAX(props.minimumValue,
|
||||
MIN(props.maximumValue,
|
||||
props.minimumValue + round((value - props.minimumValue) / props.step) * props.step
|
||||
)
|
||||
);
|
||||
|
||||
[_sliderView setValue:value animated:YES];
|
||||
}
|
||||
|
||||
if (continuous && _previousValue != value) {
|
||||
std::dynamic_pointer_cast<const SliderEventEmitter>(_eventEmitter)->onValueChange(value);
|
||||
}
|
||||
if (!continuous) {
|
||||
std::dynamic_pointer_cast<const SliderEventEmitter>(_eventEmitter)->onSlidingComplete(value);
|
||||
}
|
||||
|
||||
_previousValue = value;
|
||||
}
|
||||
|
||||
#pragma mark - RCTImageResponseDelegate
|
||||
|
||||
- (void)didReceiveImage:(UIImage *)image fromObserver:(void *)observer
|
||||
{
|
||||
if (observer == _trackImageResponseObserverProxy.get()) {
|
||||
self.trackImage = image;
|
||||
} else if (observer == _minimumTrackImageResponseObserverProxy.get()) {
|
||||
self.minimumTrackImage = image;
|
||||
} else if (observer == _maximumTrackImageResponseObserverProxy.get()) {
|
||||
self.maximumTrackImage = image;
|
||||
} else if (observer == _thumbImageResponseObserverProxy.get()) {
|
||||
self.thumbImage = image;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void *)observer {
|
||||
}
|
||||
|
||||
- (void)didReceiveFailureFromObserver:(void *)observer {
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol RCTImageResponseDelegate <NSObject>
|
||||
|
||||
- (void)didReceiveImage:(UIImage *)image fromObserver:(void*)observer;
|
||||
- (void)didReceiveProgress:(float)progress fromObserver:(void*)observer;
|
||||
- (void)didReceiveFailureFromObserver:(void*)observer;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#import "RCTImageResponseDelegate.h"
|
||||
#import "RCTImageResponseDelegate.h"
|
||||
|
||||
#include <react/imagemanager/ImageResponseObserver.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
class RCTImageResponseObserverProxy: public ImageResponseObserver {
|
||||
public:
|
||||
RCTImageResponseObserverProxy(void* delegate);
|
||||
void didReceiveImage(const ImageResponse &imageResponse) override;
|
||||
void didReceiveProgress (float p) override;
|
||||
void didReceiveFailure() override;
|
||||
|
||||
private:
|
||||
id<RCTImageResponseDelegate> delegate_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* 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 "RCTImageResponseObserverProxy.h"
|
||||
|
||||
#import <react/imagemanager/ImageResponseObserver.h>
|
||||
#import <react/imagemanager/ImageResponse.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
RCTImageResponseObserverProxy::RCTImageResponseObserverProxy(void* delegate): delegate_((__bridge id<RCTImageResponseDelegate>)delegate) {}
|
||||
|
||||
void RCTImageResponseObserverProxy::didReceiveImage(const ImageResponse &imageResponse) {
|
||||
UIImage *image = (__bridge UIImage *)imageResponse.getImage().get();
|
||||
void *this_ = this;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[delegate_ didReceiveImage:image fromObserver:this_];
|
||||
});
|
||||
}
|
||||
|
||||
void RCTImageResponseObserverProxy::didReceiveProgress (float p) {
|
||||
void *this_ = this;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[delegate_ didReceiveProgress:p fromObserver:this_];
|
||||
});
|
||||
}
|
||||
|
||||
void RCTImageResponseObserverProxy::didReceiveFailure() {
|
||||
void *this_ = this;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[delegate_ didReceiveFailureFromObserver:this_];
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -55,8 +55,10 @@ rn_xplat_cxx_library(
|
|||
"xplat//yoga:yoga",
|
||||
react_native_xplat_target("fabric/debug:debug"),
|
||||
react_native_xplat_target("fabric/core:core"),
|
||||
react_native_xplat_target("fabric/graphics:graphics"),
|
||||
react_native_xplat_target("fabric/components/image:image"),
|
||||
react_native_xplat_target("fabric/components/view:view"),
|
||||
react_native_xplat_target("fabric/graphics:graphics"),
|
||||
react_native_xplat_target("fabric/imagemanager:imagemanager"),
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -13,7 +13,37 @@
|
|||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
using SliderComponentDescriptor = ConcreteComponentDescriptor<SliderShadowNode>;
|
||||
/*
|
||||
* Descriptor for <Slider> component.
|
||||
*/
|
||||
class SliderComponentDescriptor final
|
||||
: public ConcreteComponentDescriptor<SliderShadowNode> {
|
||||
public:
|
||||
SliderComponentDescriptor(
|
||||
SharedEventDispatcher eventDispatcher,
|
||||
const SharedContextContainer &contextContainer)
|
||||
: ConcreteComponentDescriptor(eventDispatcher),
|
||||
imageManager_(
|
||||
contextContainer
|
||||
? contextContainer->getInstance<SharedImageManager>(
|
||||
"ImageManager")
|
||||
: nullptr) {}
|
||||
|
||||
void adopt(UnsharedShadowNode shadowNode) const override {
|
||||
ConcreteComponentDescriptor::adopt(shadowNode);
|
||||
|
||||
assert(std::dynamic_pointer_cast<SliderShadowNode>(shadowNode));
|
||||
auto sliderShadowNode =
|
||||
std::static_pointer_cast<SliderShadowNode>(shadowNode);
|
||||
|
||||
// `SliderShadowNode` uses `ImageManager` to initiate image loading and
|
||||
// communicate the loading state and results to mounting layer.
|
||||
sliderShadowNode->setImageManager(imageManager_);
|
||||
}
|
||||
|
||||
private:
|
||||
const SharedImageManager imageManager_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "SliderLocalData.h"
|
||||
|
||||
#include <react/components/image/conversions.h>
|
||||
#include <react/debug/debugStringConvertibleUtils.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
ImageSource SliderLocalData::getTrackImageSource() const {
|
||||
return trackImageSource_;
|
||||
}
|
||||
|
||||
const ImageRequest &SliderLocalData::getTrackImageRequest() const {
|
||||
return trackImageRequest_;
|
||||
}
|
||||
|
||||
ImageSource SliderLocalData::getMinimumTrackImageSource() const {
|
||||
return minimumTrackImageSource_;
|
||||
}
|
||||
|
||||
const ImageRequest &SliderLocalData::getMinimumTrackImageRequest() const {
|
||||
return minimumTrackImageRequest_;
|
||||
}
|
||||
|
||||
ImageSource SliderLocalData::getMaximumTrackImageSource() const {
|
||||
return maximumTrackImageSource_;
|
||||
}
|
||||
|
||||
const ImageRequest &SliderLocalData::getMaximumTrackImageRequest() const {
|
||||
return maximumTrackImageRequest_;
|
||||
}
|
||||
|
||||
ImageSource SliderLocalData::getThumbImageSource() const {
|
||||
return thumbImageSource_;
|
||||
}
|
||||
|
||||
const ImageRequest &SliderLocalData::getThumbImageRequest() const {
|
||||
return thumbImageRequest_;
|
||||
}
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
std::string SliderLocalData::getDebugName() const {
|
||||
return "SliderLocalData";
|
||||
}
|
||||
|
||||
SharedDebugStringConvertibleList SliderLocalData::getDebugProps() const {
|
||||
return {
|
||||
debugStringConvertibleItem("trackImageSource", trackImageSource_),
|
||||
debugStringConvertibleItem(
|
||||
"minimumTrackImageSource", minimumTrackImageSource_),
|
||||
debugStringConvertibleItem(
|
||||
"maximumTrackImageSource", maximumTrackImageSource_),
|
||||
debugStringConvertibleItem("thumbImageSource", thumbImageSource_),
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/core/LocalData.h>
|
||||
#include <react/imagemanager/ImageRequest.h>
|
||||
#include <react/imagemanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class SliderLocalData;
|
||||
|
||||
using SharedSliderLocalData = std::shared_ptr<const SliderLocalData>;
|
||||
|
||||
/*
|
||||
* LocalData for <Slider> component.
|
||||
* Represents the image request state and (possible) retrieved image bitmap.
|
||||
*/
|
||||
class SliderLocalData : public LocalData {
|
||||
public:
|
||||
SliderLocalData(
|
||||
const ImageSource &trackImageSource,
|
||||
ImageRequest trackImageRequest,
|
||||
const ImageSource &minimumTrackImageSource,
|
||||
ImageRequest minimumTrackImageRequest,
|
||||
const ImageSource &maximumTrackImageSource,
|
||||
ImageRequest maximumTrackImageRequest,
|
||||
const ImageSource &thumbImageSource,
|
||||
ImageRequest thumbImageRequest)
|
||||
: trackImageSource_(trackImageSource),
|
||||
trackImageRequest_(std::move(trackImageRequest)),
|
||||
minimumTrackImageSource_(minimumTrackImageSource),
|
||||
minimumTrackImageRequest_(std::move(minimumTrackImageRequest)),
|
||||
maximumTrackImageSource_(maximumTrackImageSource),
|
||||
maximumTrackImageRequest_(std::move(maximumTrackImageRequest)),
|
||||
thumbImageSource_(thumbImageSource),
|
||||
thumbImageRequest_(std::move(thumbImageRequest)){};
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getTrackImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
const ImageRequest &getTrackImageRequest() const;
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getMinimumTrackImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
const ImageRequest &getMinimumTrackImageRequest() const;
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getMaximumTrackImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
const ImageRequest &getMaximumTrackImageRequest() const;
|
||||
|
||||
/*
|
||||
* Returns stored ImageSource object.
|
||||
*/
|
||||
ImageSource getThumbImageSource() const;
|
||||
|
||||
/*
|
||||
* Exposes for reading stored `ImageRequest` object.
|
||||
* `ImageRequest` object cannot be copied or moved from `ImageLocalData`.
|
||||
*/
|
||||
const ImageRequest &getThumbImageRequest() const;
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
#if RN_DEBUG_STRING_CONVERTIBLE
|
||||
std::string getDebugName() const override;
|
||||
SharedDebugStringConvertibleList getDebugProps() const override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
ImageSource trackImageSource_;
|
||||
ImageRequest trackImageRequest_;
|
||||
ImageSource minimumTrackImageSource_;
|
||||
ImageRequest minimumTrackImageRequest_;
|
||||
ImageSource maximumTrackImageSource_;
|
||||
ImageRequest maximumTrackImageRequest_;
|
||||
ImageSource thumbImageSource_;
|
||||
ImageRequest thumbImageRequest_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <react/components/slider/SliderProps.h>
|
||||
#include <react/components/image/conversions.h>
|
||||
#include <react/core/propsConversions.h>
|
||||
|
||||
namespace facebook {
|
||||
|
@ -16,24 +17,54 @@ SliderProps::SliderProps(
|
|||
const RawProps &rawProps)
|
||||
: ViewProps(sourceProps, rawProps),
|
||||
value(convertRawProp(rawProps, "value", sourceProps.value, value)),
|
||||
steps(convertRawProp(rawProps, "steps", sourceProps.steps, steps)),
|
||||
minimumValue(convertRawProp(
|
||||
rawProps,
|
||||
"minimumValue",
|
||||
sourceProps.minimumValue,
|
||||
minimumValue)),
|
||||
maximumValue(convertRawProp(
|
||||
rawProps,
|
||||
"maximumValue",
|
||||
sourceProps.maximumValue,
|
||||
maximumValue)),
|
||||
step(convertRawProp(rawProps, "step", sourceProps.step, step)),
|
||||
disabled(
|
||||
convertRawProp(rawProps, "disabled", sourceProps.disabled, disabled)),
|
||||
minimumTrackTintColor(convertRawProp(
|
||||
rawProps,
|
||||
"minimumTintColor",
|
||||
sourceProps.thumbTintColor,
|
||||
thumbTintColor)),
|
||||
"minimumTrackTintColor",
|
||||
sourceProps.minimumTrackTintColor,
|
||||
minimumTrackTintColor)),
|
||||
maximumTrackTintColor(convertRawProp(
|
||||
rawProps,
|
||||
"maximumTintColor",
|
||||
sourceProps.thumbTintColor,
|
||||
thumbTintColor)),
|
||||
"maximumTrackTintColor",
|
||||
sourceProps.maximumTrackTintColor,
|
||||
maximumTrackTintColor)),
|
||||
thumbTintColor(convertRawProp(
|
||||
rawProps,
|
||||
"thumbTintColor",
|
||||
sourceProps.thumbTintColor,
|
||||
thumbTintColor)) {}
|
||||
thumbTintColor)),
|
||||
trackImage(convertRawProp(
|
||||
rawProps,
|
||||
"trackImage",
|
||||
sourceProps.trackImage,
|
||||
trackImage)),
|
||||
minimumTrackImage(convertRawProp(
|
||||
rawProps,
|
||||
"minimumTrackImage",
|
||||
sourceProps.minimumTrackImage,
|
||||
minimumTrackImage)),
|
||||
maximumTrackImage(convertRawProp(
|
||||
rawProps,
|
||||
"maximumTrackImage",
|
||||
sourceProps.maximumTrackImage,
|
||||
maximumTrackImage)),
|
||||
thumbImage(convertRawProp(
|
||||
rawProps,
|
||||
"thumbImage",
|
||||
sourceProps.thumbImage,
|
||||
thumbImage)) {}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <react/components/view/ViewProps.h>
|
||||
#include <react/graphics/Color.h>
|
||||
#include <react/imagemanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
@ -19,14 +22,22 @@ class SliderProps final : public ViewProps {
|
|||
|
||||
#pragma mark - Props
|
||||
|
||||
const float value{false};
|
||||
const float steps{false};
|
||||
const float value{0};
|
||||
const float minimumValue{0};
|
||||
const float maximumValue{1};
|
||||
const float step{0};
|
||||
const bool disabled{false};
|
||||
const SharedColor minimumTrackTintColor{};
|
||||
const SharedColor maximumTrackTintColor{};
|
||||
|
||||
// Android only
|
||||
const SharedColor thumbTintColor;
|
||||
|
||||
// iOS only
|
||||
const ImageSource trackImage{};
|
||||
const ImageSource minimumTrackImage{};
|
||||
const ImageSource maximumTrackImage{};
|
||||
const ImageSource thumbImage{};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
|
|
|
@ -7,10 +7,89 @@
|
|||
|
||||
#include "SliderShadowNode.h"
|
||||
|
||||
#include <react/components/slider/SliderLocalData.h>
|
||||
#include <react/components/slider/SliderShadowNode.h>
|
||||
#include <react/core/LayoutContext.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
extern const char SliderComponentName[] = "Slider";
|
||||
|
||||
void SliderShadowNode::setImageManager(const SharedImageManager &imageManager) {
|
||||
ensureUnsealed();
|
||||
imageManager_ = imageManager;
|
||||
}
|
||||
|
||||
void SliderShadowNode::updateLocalData() {
|
||||
const auto &newTrackImageSource = getTrackImageSource();
|
||||
const auto &newMinimumTrackImageSource = getMinimumTrackImageSource();
|
||||
const auto &newMaximumTrackImageSource = getMaximumTrackImageSource();
|
||||
const auto &newThumbImageSource = getThumbImageSource();
|
||||
|
||||
const auto &localData = getLocalData();
|
||||
if (localData) {
|
||||
assert(std::dynamic_pointer_cast<const SliderLocalData>(localData));
|
||||
auto currentLocalData =
|
||||
std::static_pointer_cast<const SliderLocalData>(localData);
|
||||
|
||||
auto trackImageSource = currentLocalData->getTrackImageSource();
|
||||
auto minimumTrackImageSource =
|
||||
currentLocalData->getMinimumTrackImageSource();
|
||||
auto maximumTrackImageSource =
|
||||
currentLocalData->getMaximumTrackImageSource();
|
||||
auto thumbImageSource = currentLocalData->getThumbImageSource();
|
||||
|
||||
bool anyChanged = newTrackImageSource != trackImageSource ||
|
||||
newMinimumTrackImageSource != minimumTrackImageSource ||
|
||||
newMaximumTrackImageSource != maximumTrackImageSource ||
|
||||
newThumbImageSource != thumbImageSource;
|
||||
|
||||
if (!anyChanged) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we are about to mutate the Shadow Node.
|
||||
ensureUnsealed();
|
||||
|
||||
// It is not possible to copy or move image requests from SliderLocalData,
|
||||
// so instead we recreate any image requests (that may already be in-flight?)
|
||||
// TODO: check if multiple requests are cached or if it's a net loss
|
||||
const auto &newLocalData = std::make_shared<SliderLocalData>(
|
||||
newTrackImageSource,
|
||||
imageManager_->requestImage(newTrackImageSource),
|
||||
newMinimumTrackImageSource,
|
||||
imageManager_->requestImage(newMinimumTrackImageSource),
|
||||
newMaximumTrackImageSource,
|
||||
imageManager_->requestImage(newMaximumTrackImageSource),
|
||||
newThumbImageSource,
|
||||
imageManager_->requestImage(newThumbImageSource));
|
||||
setLocalData(newLocalData);
|
||||
}
|
||||
|
||||
ImageSource SliderShadowNode::getTrackImageSource() const {
|
||||
return getProps()->trackImage;
|
||||
}
|
||||
|
||||
ImageSource SliderShadowNode::getMinimumTrackImageSource() const {
|
||||
return getProps()->minimumTrackImage;
|
||||
}
|
||||
|
||||
ImageSource SliderShadowNode::getMaximumTrackImageSource() const {
|
||||
return getProps()->maximumTrackImage;
|
||||
}
|
||||
|
||||
ImageSource SliderShadowNode::getThumbImageSource() const {
|
||||
return getProps()->thumbImage;
|
||||
}
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void SliderShadowNode::layout(LayoutContext layoutContext) {
|
||||
updateLocalData();
|
||||
ConcreteViewShadowNode::layout(layoutContext);
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <react/components/slider/SliderEventEmitter.h>
|
||||
#include <react/components/slider/SliderProps.h>
|
||||
#include <react/components/view/ConcreteViewShadowNode.h>
|
||||
#include <react/imagemanager/ImageManager.h>
|
||||
#include <react/imagemanager/primitives.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
@ -19,10 +21,31 @@ extern const char SliderComponentName[];
|
|||
/*
|
||||
* `ShadowNode` for <Slider> component.
|
||||
*/
|
||||
using SliderShadowNode = ConcreteViewShadowNode<
|
||||
SliderComponentName,
|
||||
SliderProps,
|
||||
SliderEventEmitter>;
|
||||
class SliderShadowNode final : public ConcreteViewShadowNode<
|
||||
SliderComponentName,
|
||||
SliderProps,
|
||||
SliderEventEmitter> {
|
||||
public:
|
||||
using ConcreteViewShadowNode::ConcreteViewShadowNode;
|
||||
|
||||
// Associates a shared `ImageManager` with the node.
|
||||
void setImageManager(const SharedImageManager &imageManager);
|
||||
|
||||
#pragma mark - LayoutableShadowNode
|
||||
|
||||
void layout(LayoutContext layoutContext) override;
|
||||
|
||||
private:
|
||||
// (Re)Creates a `LocalData` object (with `ImageRequest`) if needed.
|
||||
void updateLocalData();
|
||||
|
||||
ImageSource getTrackImageSource() const;
|
||||
ImageSource getMinimumTrackImageSource() const;
|
||||
ImageSource getMaximumTrackImageSource() const;
|
||||
ImageSource getThumbImageSource() const;
|
||||
|
||||
SharedImageManager imageManager_;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
|
Загрузка…
Ссылка в новой задаче