/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.react.views.image; import javax.annotation.Nullable; import java.util.Map; import android.graphics.Color; import android.graphics.PorterDuff.Mode; import com.facebook.yoga.YogaConstants; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.controller.AbstractDraweeControllerBuilder; import com.facebook.react.bridge.JSApplicationIllegalArgumentException; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.MapBuilder; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.uimanager.PixelUtil; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewProps; import com.facebook.react.uimanager.annotations.ReactProp; import com.facebook.react.uimanager.annotations.ReactPropGroup; @ReactModule(name = ReactImageManager.REACT_CLASS) public class ReactImageManager extends SimpleViewManager<ReactImageView> { protected static final String REACT_CLASS = "RCTImageView"; @Override public String getName() { return REACT_CLASS; } private @Nullable AbstractDraweeControllerBuilder mDraweeControllerBuilder; private final @Nullable Object mCallerContext; public ReactImageManager( AbstractDraweeControllerBuilder draweeControllerBuilder, Object callerContext) { mDraweeControllerBuilder = draweeControllerBuilder; mCallerContext = callerContext; } public ReactImageManager() { // Lazily initialize as FrescoModule have not been initialized yet mDraweeControllerBuilder = null; mCallerContext = null; } public AbstractDraweeControllerBuilder getDraweeControllerBuilder() { if (mDraweeControllerBuilder == null) { mDraweeControllerBuilder = Fresco.newDraweeControllerBuilder(); } return mDraweeControllerBuilder; } public Object getCallerContext() { return mCallerContext; } @Override public ReactImageView createViewInstance(ThemedReactContext context) { return new ReactImageView( context, getDraweeControllerBuilder(), getCallerContext()); } // In JS this is Image.props.source @ReactProp(name = "src") public void setSource(ReactImageView view, @Nullable ReadableArray sources) { view.setSource(sources); } // In JS this is Image.props.loadingIndicatorSource.uri @ReactProp(name = "loadingIndicatorSrc") public void setLoadingIndicatorSource(ReactImageView view, @Nullable String source) { view.setLoadingIndicatorSource(source); } @ReactProp(name = "borderColor", customType = "Color") public void setBorderColor(ReactImageView view, @Nullable Integer borderColor) { if (borderColor == null) { view.setBorderColor(Color.TRANSPARENT); } else { view.setBorderColor(borderColor); } } @ReactProp(name = "overlayColor") public void setOverlayColor(ReactImageView view, @Nullable Integer overlayColor) { if (overlayColor == null) { view.setOverlayColor(Color.TRANSPARENT); } else { view.setOverlayColor(overlayColor); } } @ReactProp(name = "borderWidth") public void setBorderWidth(ReactImageView view, float borderWidth) { view.setBorderWidth(borderWidth); } @ReactPropGroup(names = { ViewProps.BORDER_RADIUS, ViewProps.BORDER_TOP_LEFT_RADIUS, ViewProps.BORDER_TOP_RIGHT_RADIUS, ViewProps.BORDER_BOTTOM_RIGHT_RADIUS, ViewProps.BORDER_BOTTOM_LEFT_RADIUS }, defaultFloat = YogaConstants.UNDEFINED) public void setBorderRadius(ReactImageView view, int index, float borderRadius) { if (!YogaConstants.isUndefined(borderRadius)) { borderRadius = PixelUtil.toPixelFromDIP(borderRadius); } if (index == 0) { view.setBorderRadius(borderRadius); } else { view.setBorderRadius(borderRadius, index - 1); } } @ReactProp(name = ViewProps.RESIZE_MODE) public void setResizeMode(ReactImageView view, @Nullable String resizeMode) { view.setScaleType(ImageResizeMode.toScaleType(resizeMode)); } @ReactProp(name = ViewProps.RESIZE_METHOD) public void setResizeMethod(ReactImageView view, @Nullable String resizeMethod) { if (resizeMethod == null || "auto".equals(resizeMethod)) { view.setResizeMethod(ImageResizeMethod.AUTO); } else if ("resize".equals(resizeMethod)) { view.setResizeMethod(ImageResizeMethod.RESIZE); } else if ("scale".equals(resizeMethod)) { view.setResizeMethod(ImageResizeMethod.SCALE); } else { throw new JSApplicationIllegalArgumentException("Invalid resize method: '" + resizeMethod+ "'"); } } @ReactProp(name = "tintColor", customType = "Color") public void setTintColor(ReactImageView view, @Nullable Integer tintColor) { if (tintColor == null) { view.clearColorFilter(); } else { view.setColorFilter(tintColor, Mode.SRC_IN); } } @ReactProp(name = "progressiveRenderingEnabled") public void setProgressiveRenderingEnabled(ReactImageView view, boolean enabled) { view.setProgressiveRenderingEnabled(enabled); } @ReactProp(name = "fadeDuration") public void setFadeDuration(ReactImageView view, int durationMs) { view.setFadeDuration(durationMs); } @ReactProp(name = "shouldNotifyLoadEvents") public void setLoadHandlersRegistered(ReactImageView view, boolean shouldNotifyLoadEvents) { view.setShouldNotifyLoadEvents(shouldNotifyLoadEvents); } @ReactProp(name = "headers") public void setHeaders(ReactImageView view, ReadableMap headers) { view.setHeaders(headers); } @Override public @Nullable Map getExportedCustomDirectEventTypeConstants() { return MapBuilder.of( ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_START), MapBuilder.of("registrationName", "onLoadStart"), ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD), MapBuilder.of("registrationName", "onLoad"), ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_ERROR), MapBuilder.of("registrationName", "onError"), ImageLoadEvent.eventNameForType(ImageLoadEvent.ON_LOAD_END), MapBuilder.of("registrationName", "onLoadEnd")); } @Override protected void onAfterUpdateTransaction(ReactImageView view) { super.onAfterUpdateTransaction(view); view.maybeUpdateView(); } }