Permalink
Browse files

match RN attachment images Feed experience with Native with spinner/f…

…ade in

Reviewed By: astreet

Differential Revision: D2722917

fb-gh-sync-id: a09b9a1a4b9a19b94471d8e93ec5bde53af7da06
  • Loading branch information...
Olivier Notteghem facebook-github-bot-7
Olivier Notteghem authored and facebook-github-bot-7 committed Dec 6, 2015
1 parent f1a575e commit a38ce5c5705a18379d3f54297fad3b5b241611a0
@@ -53,6 +53,7 @@ var resolveAssetSource = require('resolveAssetSource');
var ImageViewAttributes = merge(ReactNativeViewAttributes.UIView, {
src: true,
+ loadingIndicatorSrc: true,
resizeMode: true,
progressiveRenderingEnabled: true,
fadeDuration: true,
@@ -74,6 +75,18 @@ var Image = React.createClass({
// Opaque type returned by require('./image.jpg')
PropTypes.number,
]).isRequired,
+ /**
+ * similarly to `source`, this property represents the resource used to render
+ * the loading indicator for the image, displayed until image is ready to be
+ * displayed, typically after when it got downloaded from network.
+ */
+ loadingIndicatorSource: PropTypes.oneOfType([
+ PropTypes.shape({
+ uri: PropTypes.string,
+ }),
+ // Opaque type returned by require('./image.jpg')
+ PropTypes.number,
+ ]),
progressiveRenderingEnabled: PropTypes.bool,
fadeDuration: PropTypes.number,
/**
@@ -138,6 +151,7 @@ var Image = React.createClass({
render: function() {
var source = resolveAssetSource(this.props.source);
+ var loadingIndicatorSource = resolveAssetSource(this.props.loadingIndicatorSource);
// As opposed to the ios version, here it render `null`
// when no source or source.uri... so let's not break that.
@@ -155,6 +169,7 @@ var Image = React.createClass({
style,
shouldNotifyLoadEvents: !!(onLoadStart || onLoad || onLoadEnd),
src: source.uri,
+ loadingIndicatorSrc: loadingIndicatorSource ? loadingIndicatorSource.uri : null,
});
if (nativeProps.children) {
@@ -197,6 +212,7 @@ var styles = StyleSheet.create({
var cfg = {
nativeOnly: {
src: true,
+ loadingIndicatorSrc: true,
defaultImageSrc: true,
imageTag: true,
progressHandlerRegistered: true,
@@ -73,6 +73,12 @@ public void setSource(ReactImageView view, @Nullable String source) {
view.setSource(source);
}
+ // 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) {
@@ -15,6 +15,7 @@
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -26,6 +27,7 @@
import com.facebook.common.util.UriUtil;
import com.facebook.drawee.controller.AbstractDraweeControllerBuilder;
+import com.facebook.drawee.drawable.AutoRotateDrawable;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.controller.ControllerListener;
import com.facebook.drawee.controller.ForwardingControllerListener;
@@ -104,6 +106,7 @@ public void process(Bitmap output, Bitmap source) {
}
private @Nullable Uri mUri;
+ private @Nullable Drawable mLoadingImageDrawable;
private int mBorderColor;
private float mBorderWidth;
private float mBorderRadius;
@@ -220,6 +223,13 @@ public void setSource(@Nullable String source) {
mIsDirty = true;
}
+ public void setLoadingIndicatorSource(@Nullable String name) {
+ Drawable drawable = getResourceDrawable(getContext(), name);
+ mLoadingImageDrawable =
+ drawable != null ? (Drawable) new AutoRotateDrawable(drawable, 1000) : null;
+ mIsDirty = true;
+ }
+
public void setProgressiveRenderingEnabled(boolean enabled) {
mProgressiveRenderingEnabled = enabled;
// no worth marking as dirty if it already rendered..
@@ -244,6 +254,10 @@ public void maybeUpdateView() {
GenericDraweeHierarchy hierarchy = getHierarchy();
hierarchy.setActualImageScaleType(mScaleType);
+ if (mLoadingImageDrawable != null) {
+ hierarchy.setPlaceholderImage(mLoadingImageDrawable, ScalingUtils.ScaleType.CENTER);
+ }
+
boolean usePostprocessorScaling =
mScaleType != ScalingUtils.ScaleType.CENTER_CROP &&
mScaleType != ScalingUtils.ScaleType.FOCUS_CROP;
@@ -322,18 +336,26 @@ private static boolean shouldResize(@Nullable Uri uri) {
return uri != null && (UriUtil.isLocalContentUri(uri) || UriUtil.isLocalFileUri(uri));
}
- private static @Nullable Uri getResourceDrawableUri(Context context, @Nullable String name) {
+ private static int getResourceDrawableId(Context context, @Nullable String name) {
if (name == null || name.isEmpty()) {
- return null;
+ return 0;
}
- name = name.toLowerCase().replace("-", "_");
- int resId = context.getResources().getIdentifier(
- name,
+ return context.getResources().getIdentifier(
+ name.toLowerCase().replace("-", "_"),
"drawable",
context.getPackageName());
- return new Uri.Builder()
+ }
+
+ private static @Nullable Drawable getResourceDrawable(Context context, @Nullable String name) {
+ int resId = getResourceDrawableId(context, name);
+ return resId > 0 ? context.getResources().getDrawable(resId) : null;
+ }
+
+ private static @Nullable Uri getResourceDrawableUri(Context context, @Nullable String name) {
+ int resId = getResourceDrawableId(context, name);
+ return resId > 0 ? new Uri.Builder()
.scheme(UriUtil.LOCAL_RESOURCE_SCHEME)
.path(String.valueOf(resId))
- .build();
+ .build() : null;
}
}

2 comments on commit a38ce5c

@brentvatne

This comment has been minimized.

Show comment
Hide comment
@brentvatne

brentvatne Dec 7, 2015

Collaborator

👍 beauty

Collaborator

brentvatne replied Dec 7, 2015

👍 beauty

@brentvatne

This comment has been minimized.

Show comment
Hide comment
@brentvatne

brentvatne Dec 7, 2015

Collaborator

Actually, is this not the same as defaultSource on iOS? Maybe we should use the same prop name. https://github.com/facebook/react-native/blob/master/Libraries/Image/Image.ios.js#L71-L78

Collaborator

brentvatne replied Dec 7, 2015

Actually, is this not the same as defaultSource on iOS? Maybe we should use the same prop name. https://github.com/facebook/react-native/blob/master/Libraries/Image/Image.ios.js#L71-L78

Please sign in to comment.