Skip to content

Instantly share code, notes, and snippets.

@cristiangu
Last active September 2, 2023 14:38
Show Gist options
  • Save cristiangu/3b5b016b06b43a401ee0b015a4101ae4 to your computer and use it in GitHub Desktop.
Save cristiangu/3b5b016b06b43a401ee0b015a4101ae4 to your computer and use it in GitHub Desktop.
react-native-fast-image patch diff to fix the image change flickering
import FastImage from 'react-native-fast-image';
return (
<FastImage
useLastImageAsDefaultSource
source={source}
/>
);
@ReactProp(name = "useLastImageAsDefaultSource")
public void useLastImageAsDefaultSource(FastImageViewWithUrl view, @Nullable Boolean isActivated) {
view.useLastImageAsDefaultSource(isActivated);
}
private Boolean mUseLastImageAsDefaultSource = false;
[...]
public void useLastImageAsDefaultSource(@Nullable Boolean isActivated) {
mUseLastImageAsDefaultSource = isActivated;
}
[...]
if (requestManager != null) {
RequestBuilder<Drawable> builder =
requestManager
// This will make this work for remote and local images. e.g.
// - file:///
// - content://
// - res:/
// - android.resource://
// - data:image/png;base64
.load(imageSource == null ? null : imageSource.getSourceForLoad())
.apply(FastImageViewConverter
.getOptions(context, imageSource, mSource)
.placeholder(mUseLastImageAsDefaultSource ? this.getDrawable() : mDefaultSource) // show until loaded
.fallback(mDefaultSource)); // null will not be treated as error
if (key != null)
builder.listener(new FastImageRequestListener(key));
builder.into(this);
}
}
@property (nonatomic, assign) BOOL useLastImageAsDefaultSource;
[...]
- (void) setUseLastImageAsDefaultSource: (BOOL*)useLastImageAsDefaultSource {
if (useLastImageAsDefaultSource != _useLastImageAsDefaultSource) {
_useLastImageAsDefaultSource = useLastImageAsDefaultSource;
}
}
[...]
- (void) downloadImage: (FFFastImageSource*)source options: (SDWebImageOptions)options context: (SDWebImageContext*)context {
__weak typeof(self) weakSelf = self; // Always use a weak reference to self in blocks
[self sd_setImageWithURL: _source.url
placeholderImage: _useLastImageAsDefaultSource == YES ? [super image] : _defaultSource
options: options
context: context
progress: ^(NSInteger receivedSize, NSInteger expectedSize, NSURL* _Nullable targetURL) {
if (weakSelf.onFastImageProgress) {
weakSelf.onFastImageProgress(@{
@"loaded": @(receivedSize),
@"total": @(expectedSize)
});
}
}
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java
index c7a7954..ca2b394 100644
--- a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java
@@ -68,6 +68,11 @@ class FastImageViewManager extends SimpleViewManager<FastImageViewWithUrl> imple
.getResourceDrawable(view.getContext(), source));
}
+ @ReactProp(name = "useLastImageAsDefaultSource")
+ public void useLastImageAsDefaultSource(FastImageViewWithUrl view, @Nullable Boolean isActivated) {
+ view.useLastImageAsDefaultSource(isActivated);
+ }
+
@ReactProp(name = "tintColor", customType = "Color")
public void setTintColor(FastImageViewWithUrl view, @Nullable Integer color) {
if (color == null) {
diff --git a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java
index 34fcf89..4e3c633 100644
--- a/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java
+++ b/node_modules/react-native-fast-image/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java
@@ -1,5 +1,6 @@
package com.dylanvann.fastimage;
+import static com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade;
import static com.dylanvann.fastimage.FastImageRequestListener.REACT_ON_ERROR_EVENT;
import android.annotation.SuppressLint;
@@ -9,10 +10,12 @@ import android.graphics.drawable.Drawable;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageView;
+import com.bumptech.glide.GenericTransitionOptions;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.load.model.GlideUrl;
import com.bumptech.glide.request.Request;
+import com.bumptech.glide.request.transition.DrawableCrossFadeTransition;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
@@ -30,6 +33,7 @@ class FastImageViewWithUrl extends AppCompatImageView {
private boolean mNeedsReload = false;
private ReadableMap mSource = null;
private Drawable mDefaultSource = null;
+ private Boolean mUseLastImageAsDefaultSource = false;
public GlideUrl glideUrl;
@@ -47,6 +51,10 @@ class FastImageViewWithUrl extends AppCompatImageView {
mDefaultSource = source;
}
+ public void useLastImageAsDefaultSource(@Nullable Boolean isActivated) {
+ mUseLastImageAsDefaultSource = isActivated;
+ }
+
private boolean isNullOrEmpty(final String url) {
return url == null || url.trim().isEmpty();
}
@@ -141,12 +149,11 @@ class FastImageViewWithUrl extends AppCompatImageView {
.load(imageSource == null ? null : imageSource.getSourceForLoad())
.apply(FastImageViewConverter
.getOptions(context, imageSource, mSource)
- .placeholder(mDefaultSource) // show until loaded
+ .placeholder(mUseLastImageAsDefaultSource ? this.getDrawable() : mDefaultSource) // show until loaded
.fallback(mDefaultSource)); // null will not be treated as error
if (key != null)
builder.listener(new FastImageRequestListener(key));
-
builder.into(this);
}
}
diff --git a/node_modules/react-native-fast-image/dist/index.d.ts b/node_modules/react-native-fast-image/dist/index.d.ts
index 5abb7c9..7173cde 100644
--- a/node_modules/react-native-fast-image/dist/index.d.ts
+++ b/node_modules/react-native-fast-image/dist/index.d.ts
@@ -89,6 +89,7 @@ export interface FastImageProps extends AccessibilityProps, ViewProps {
* Render children within the image.
*/
children?: React.ReactNode;
+ useLastImageAsDefaultSource?: boolean;
}
export interface FastImageStaticProperties {
resizeMode: typeof resizeMode;
diff --git a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
index e52fca7..08a0a6d 100644
--- a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
+++ b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.h
@@ -19,6 +19,6 @@
@property (nonatomic, strong) FFFastImageSource *source;
@property (nonatomic, strong) UIImage *defaultSource;
@property (nonatomic, strong) UIColor *imageColor;
-
+@property (nonatomic, assign) BOOL useLastImageAsDefaultSource;
@end
diff --git a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m
index f710081..4a9e486 100644
--- a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m
+++ b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageView.m
@@ -113,6 +113,12 @@ - (void) setDefaultSource: (UIImage*)defaultSource {
}
}
+- (void) setUseLastImageAsDefaultSource: (BOOL*)useLastImageAsDefaultSource {
+ if (useLastImageAsDefaultSource != _useLastImageAsDefaultSource) {
+ _useLastImageAsDefaultSource = useLastImageAsDefaultSource;
+ }
+}
+
- (void) didSetProps: (NSArray<NSString*>*)changedProps {
if (_needsReload) {
[self reloadImage];
@@ -205,7 +211,7 @@ - (void) reloadImage {
- (void) downloadImage: (FFFastImageSource*)source options: (SDWebImageOptions)options context: (SDWebImageContext*)context {
__weak typeof(self) weakSelf = self; // Always use a weak reference to self in blocks
[self sd_setImageWithURL: _source.url
- placeholderImage: _defaultSource
+ placeholderImage: _useLastImageAsDefaultSource ? [super image] : _defaultSource
options: options
context: context
progress: ^(NSInteger receivedSize, NSInteger expectedSize, NSURL* _Nullable targetURL) {
diff --git a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.m b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.m
index 84ca94e..9b8ff8c 100644
--- a/node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.m
+++ b/node_modules/react-native-fast-image/ios/FastImage/FFFastImageViewManager.m
@@ -20,6 +20,7 @@ - (FFFastImageView*)view {
RCT_EXPORT_VIEW_PROPERTY(onFastImageError, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onFastImageLoad, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onFastImageLoadEnd, RCTDirectEventBlock)
+RCT_EXPORT_VIEW_PROPERTY(useLastImageAsDefaultSource, BOOL)
RCT_REMAP_VIEW_PROPERTY(tintColor, imageColor, UIColor)
RCT_EXPORT_METHOD(preload:(nonnull NSArray<FFFastImageSource *> *)sources)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment