@depup/react-native-fast-image 8.6.3-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +25 -0
  3. package/RNFastImage.podspec +21 -0
  4. package/android/build.gradle +68 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/dylanvann/fastimage/FastImageCacheControl.java +8 -0
  7. package/android/src/main/java/com/dylanvann/fastimage/FastImageGlideModule.java +9 -0
  8. package/android/src/main/java/com/dylanvann/fastimage/FastImageOkHttpProgressGlideModule.java +176 -0
  9. package/android/src/main/java/com/dylanvann/fastimage/FastImageProgressListener.java +14 -0
  10. package/android/src/main/java/com/dylanvann/fastimage/FastImageRequestListener.java +60 -0
  11. package/android/src/main/java/com/dylanvann/fastimage/FastImageSource.java +112 -0
  12. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewConverter.java +153 -0
  13. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewManager.java +183 -0
  14. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewModule.java +89 -0
  15. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewPackage.java +25 -0
  16. package/android/src/main/java/com/dylanvann/fastimage/FastImageViewWithUrl.java +159 -0
  17. package/changes.json +5 -0
  18. package/dist/index.cjs.js +144 -0
  19. package/dist/index.cjs.js.flow +75 -0
  20. package/dist/index.d.ts +103 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +137 -0
  23. package/dist/index.js.flow +75 -0
  24. package/dist/index.test.d.ts +2 -0
  25. package/dist/index.test.d.ts.map +1 -0
  26. package/ios/FastImage/FFFastImageSource.h +33 -0
  27. package/ios/FastImage/FFFastImageSource.m +20 -0
  28. package/ios/FastImage/FFFastImageView.h +24 -0
  29. package/ios/FastImage/FFFastImageView.m +244 -0
  30. package/ios/FastImage/FFFastImageViewManager.h +5 -0
  31. package/ios/FastImage/FFFastImageViewManager.m +52 -0
  32. package/ios/FastImage/RCTConvert+FFFastImage.h +9 -0
  33. package/ios/FastImage/RCTConvert+FFFastImage.m +53 -0
  34. package/ios/FastImage.xcodeproj/project.pbxproj +479 -0
  35. package/ios/FastImage.xcodeproj/xcshareddata/xcschemes/FastImage-tvOS.xcscheme +80 -0
  36. package/package.json +98 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Dylan Vann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,25 @@
1
+ # @depup/react-native-fast-image
2
+
3
+ > Dependency-bumped version of [react-native-fast-image](https://www.npmjs.com/package/react-native-fast-image)
4
+
5
+ Generated by [DepUp](https://github.com/depup/npm) -- all production
6
+ dependencies bumped to latest versions.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @depup/react-native-fast-image
12
+ ```
13
+
14
+ | Field | Value |
15
+ |-------|-------|
16
+ | Original | [react-native-fast-image](https://www.npmjs.com/package/react-native-fast-image) @ 8.6.3 |
17
+ | Processed | 2026-03-18 |
18
+ | Smoke test | failed |
19
+ | Deps updated | 0 |
20
+
21
+ ---
22
+
23
+ Source: https://github.com/depup/npm | Original: https://www.npmjs.com/package/react-native-fast-image
24
+
25
+ License inherited from the original package.
@@ -0,0 +1,21 @@
1
+ require 'json'
2
+
3
+ Pod::Spec.new do |s|
4
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
5
+
6
+ s.name = "RNFastImage"
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.authors = { "Dylan Vann" => "dylan@dylanvann.com" }
10
+ s.homepage = "https://github.com/DylanVann/react-native-fast-image#readme"
11
+ s.license = "MIT"
12
+ s.platforms = { :ios => "8.0", :tvos => "9.0" }
13
+ s.framework = 'UIKit'
14
+ s.requires_arc = true
15
+ s.source = { :git => "https://github.com/DylanVann/react-native-fast-image.git", :tag => "v#{s.version}" }
16
+ s.source_files = "ios/**/*.{h,m}"
17
+
18
+ s.dependency 'React-Core'
19
+ s.dependency 'SDWebImage', '~> 5.11.1'
20
+ s.dependency 'SDWebImageWebPCoder', '~> 0.8.4'
21
+ end
@@ -0,0 +1,68 @@
1
+ def safeExtGet(prop, fallback) {
2
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
3
+ }
4
+
5
+ buildscript {
6
+ // The Android Gradle plugin is only required when opening the android folder stand-alone.
7
+ // This avoids unnecessary downloads and potential conflicts when the library is included as a
8
+ // module dependency in an application project.
9
+ if (project == rootProject) {
10
+ repositories {
11
+ google()
12
+ mavenCentral()
13
+ }
14
+ dependencies {
15
+ classpath 'com.android.tools.build:gradle:3.5.3'
16
+ }
17
+ }
18
+ }
19
+
20
+ apply plugin: 'com.android.library'
21
+
22
+ android {
23
+ compileSdkVersion safeExtGet('compileSdkVersion', 28)
24
+ buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3')
25
+ defaultConfig {
26
+ minSdkVersion safeExtGet('minSdkVersion', 16)
27
+ targetSdkVersion safeExtGet('targetSdkVersion', 28)
28
+ versionCode 1
29
+ versionName "1.0"
30
+ }
31
+ sourceSets {
32
+ main {
33
+ java {
34
+ if (safeExtGet('excludeAppGlideModule', false)) {
35
+ srcDir "src"
36
+ exclude "**/FastImageGlideModule.java"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ lintOptions {
42
+ abortOnError false
43
+ }
44
+ }
45
+
46
+ repositories {
47
+ mavenLocal()
48
+ maven {
49
+ // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
50
+ url "$rootDir/../node_modules/react-native/android"
51
+ }
52
+ maven {
53
+ // Android JSC is installed from npm
54
+ url "$rootDir/../node_modules/jsc-android/dist"
55
+ }
56
+ google()
57
+ mavenCentral()
58
+ }
59
+
60
+ def glideVersion = safeExtGet('glideVersion', '4.12.0')
61
+
62
+ dependencies {
63
+ //noinspection GradleDynamicVersion
64
+ implementation 'com.facebook.react:react-native:+' // From node_modules
65
+ implementation "com.github.bumptech.glide:glide:${glideVersion}"
66
+ implementation "com.github.bumptech.glide:okhttp3-integration:${glideVersion}"
67
+ annotationProcessor "com.github.bumptech.glide:compiler:${glideVersion}"
68
+ }
@@ -0,0 +1,2 @@
1
+ <manifest package="com.dylanvann.fastimage">
2
+ </manifest>
@@ -0,0 +1,8 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ public enum FastImageCacheControl {
4
+ IMMUTABLE,
5
+ WEB,
6
+ CACHE_ONLY
7
+ }
8
+
@@ -0,0 +1,9 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import com.bumptech.glide.annotation.GlideModule;
4
+ import com.bumptech.glide.module.AppGlideModule;
5
+
6
+ // We need an AppGlideModule to be present for progress events to work.
7
+ @GlideModule
8
+ public final class FastImageGlideModule extends AppGlideModule {
9
+ }
@@ -0,0 +1,176 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import android.content.Context;
4
+ import androidx.annotation.NonNull;
5
+
6
+ import com.bumptech.glide.Glide;
7
+ import com.bumptech.glide.Registry;
8
+ import com.bumptech.glide.annotation.GlideModule;
9
+ import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader;
10
+ import com.bumptech.glide.load.model.GlideUrl;
11
+ import com.bumptech.glide.module.LibraryGlideModule;
12
+ import com.facebook.react.modules.network.OkHttpClientProvider;
13
+
14
+ import java.io.IOException;
15
+ import java.io.InputStream;
16
+ import java.util.HashMap;
17
+ import java.util.Map;
18
+ import java.util.WeakHashMap;
19
+
20
+ import okhttp3.Interceptor;
21
+ import okhttp3.MediaType;
22
+ import okhttp3.OkHttpClient;
23
+ import okhttp3.Request;
24
+ import okhttp3.Response;
25
+ import okhttp3.ResponseBody;
26
+ import okio.Buffer;
27
+ import okio.BufferedSource;
28
+ import okio.ForwardingSource;
29
+ import okio.Okio;
30
+ import okio.Source;
31
+
32
+ @GlideModule
33
+ public class FastImageOkHttpProgressGlideModule extends LibraryGlideModule {
34
+
35
+ private static final DispatchingProgressListener progressListener = new DispatchingProgressListener();
36
+
37
+ @Override
38
+ public void registerComponents(
39
+ @NonNull Context context,
40
+ @NonNull Glide glide,
41
+ @NonNull Registry registry
42
+ ) {
43
+ OkHttpClient client = OkHttpClientProvider
44
+ .getOkHttpClient()
45
+ .newBuilder()
46
+ .addInterceptor(createInterceptor(progressListener))
47
+ .build();
48
+ OkHttpUrlLoader.Factory factory = new OkHttpUrlLoader.Factory(client);
49
+ registry.replace(GlideUrl.class, InputStream.class, factory);
50
+ }
51
+
52
+ private static Interceptor createInterceptor(final ResponseProgressListener listener) {
53
+ return new Interceptor() {
54
+ @Override
55
+ public Response intercept(Chain chain) throws IOException {
56
+ Request request = chain.request();
57
+ Response response = chain.proceed(request);
58
+ final String key = request.url().toString();
59
+ return response
60
+ .newBuilder()
61
+ .body(new OkHttpProgressResponseBody(key, response.body(), listener))
62
+ .build();
63
+ }
64
+ };
65
+ }
66
+
67
+ static void forget(String key) {
68
+ progressListener.forget(key);
69
+ }
70
+
71
+ static void expect(String key, FastImageProgressListener listener) {
72
+ progressListener.expect(key, listener);
73
+ }
74
+
75
+ private interface ResponseProgressListener {
76
+ void update(String key, long bytesRead, long contentLength);
77
+ }
78
+
79
+ private static class DispatchingProgressListener implements ResponseProgressListener {
80
+ private final Map<String, FastImageProgressListener> LISTENERS = new WeakHashMap<>();
81
+ private final Map<String, Long> PROGRESSES = new HashMap<>();
82
+
83
+ void forget(String key) {
84
+ LISTENERS.remove(key);
85
+ PROGRESSES.remove(key);
86
+ }
87
+
88
+ void expect(String key, FastImageProgressListener listener) {
89
+ LISTENERS.put(key, listener);
90
+ }
91
+
92
+ @Override
93
+ public void update(final String key, final long bytesRead, final long contentLength) {
94
+ final FastImageProgressListener listener = LISTENERS.get(key);
95
+ if (listener == null) {
96
+ return;
97
+ }
98
+ if (contentLength <= bytesRead) {
99
+ forget(key);
100
+ }
101
+ if (needsDispatch(key, bytesRead, contentLength, listener.getGranularityPercentage())) {
102
+ listener.onProgress(key, bytesRead, contentLength);
103
+ }
104
+ }
105
+
106
+ private boolean needsDispatch(String key, long current, long total, float granularity) {
107
+ if (granularity == 0 || current == 0 || total == current) {
108
+ return true;
109
+ }
110
+ float percent = 100f * current / total;
111
+ long currentProgress = (long) (percent / granularity);
112
+ Long lastProgress = PROGRESSES.get(key);
113
+ if (lastProgress == null || currentProgress != lastProgress) {
114
+ PROGRESSES.put(key, currentProgress);
115
+ return true;
116
+ } else {
117
+ return false;
118
+ }
119
+ }
120
+ }
121
+
122
+ private static class OkHttpProgressResponseBody extends ResponseBody {
123
+ private final String key;
124
+ private final ResponseBody responseBody;
125
+ private final ResponseProgressListener progressListener;
126
+ private BufferedSource bufferedSource;
127
+
128
+ OkHttpProgressResponseBody(
129
+ String key,
130
+ ResponseBody responseBody,
131
+ ResponseProgressListener progressListener
132
+ ) {
133
+ this.key = key;
134
+ this.responseBody = responseBody;
135
+ this.progressListener = progressListener;
136
+ }
137
+
138
+ @Override
139
+ public MediaType contentType() {
140
+ return responseBody.contentType();
141
+ }
142
+
143
+ @Override
144
+ public long contentLength() {
145
+ return responseBody.contentLength();
146
+ }
147
+
148
+ @Override
149
+ public BufferedSource source() {
150
+ if (bufferedSource == null) {
151
+ bufferedSource = Okio.buffer(source(responseBody.source()));
152
+ }
153
+ return bufferedSource;
154
+ }
155
+
156
+ private Source source(Source source) {
157
+ return new ForwardingSource(source) {
158
+ long totalBytesRead = 0L;
159
+
160
+ @Override
161
+ public long read(Buffer sink, long byteCount) throws IOException {
162
+ long bytesRead = super.read(sink, byteCount);
163
+ long fullLength = responseBody.contentLength();
164
+ if (bytesRead == -1) {
165
+ // this source is exhausted
166
+ totalBytesRead = fullLength;
167
+ } else {
168
+ totalBytesRead += bytesRead;
169
+ }
170
+ progressListener.update(key, totalBytesRead, fullLength);
171
+ return bytesRead;
172
+ }
173
+ };
174
+ }
175
+ }
176
+ }
@@ -0,0 +1,14 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ public interface FastImageProgressListener {
4
+
5
+ void onProgress(String key, long bytesRead, long expectedLength);
6
+
7
+ /**
8
+ * Control how often the listener needs an update. 0% and 100% will always be dispatched.
9
+ *
10
+ * @return in percentage (0.2 = call {@link #onProgress} around every 0.2 percent of progress)
11
+ */
12
+ float getGranularityPercentage();
13
+
14
+ }
@@ -0,0 +1,60 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import android.graphics.drawable.Drawable;
4
+
5
+ import com.bumptech.glide.load.DataSource;
6
+ import com.bumptech.glide.load.engine.GlideException;
7
+ import com.bumptech.glide.request.RequestListener;
8
+ import com.bumptech.glide.request.target.ImageViewTarget;
9
+ import com.bumptech.glide.request.target.Target;
10
+ import com.facebook.react.bridge.WritableMap;
11
+ import com.facebook.react.bridge.WritableNativeMap;
12
+ import com.facebook.react.uimanager.ThemedReactContext;
13
+ import com.facebook.react.uimanager.events.RCTEventEmitter;
14
+
15
+ public class FastImageRequestListener implements RequestListener<Drawable> {
16
+ static final String REACT_ON_ERROR_EVENT = "onFastImageError";
17
+ static final String REACT_ON_LOAD_EVENT = "onFastImageLoad";
18
+ static final String REACT_ON_LOAD_END_EVENT = "onFastImageLoadEnd";
19
+ private final String key;
20
+
21
+ FastImageRequestListener(String key) {
22
+ this.key = key;
23
+ }
24
+
25
+ private static WritableMap mapFromResource(Drawable resource) {
26
+ WritableMap resourceData = new WritableNativeMap();
27
+ resourceData.putInt("width", resource.getIntrinsicWidth());
28
+ resourceData.putInt("height", resource.getIntrinsicHeight());
29
+ return resourceData;
30
+ }
31
+
32
+ @Override
33
+ public boolean onLoadFailed(@androidx.annotation.Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
34
+ FastImageOkHttpProgressGlideModule.forget(key);
35
+ if (!(target instanceof ImageViewTarget)) {
36
+ return false;
37
+ }
38
+ FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
39
+ ThemedReactContext context = (ThemedReactContext) view.getContext();
40
+ RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
41
+ int viewId = view.getId();
42
+ eventEmitter.receiveEvent(viewId, REACT_ON_ERROR_EVENT, new WritableNativeMap());
43
+ eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
44
+ return false;
45
+ }
46
+
47
+ @Override
48
+ public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
49
+ if (!(target instanceof ImageViewTarget)) {
50
+ return false;
51
+ }
52
+ FastImageViewWithUrl view = (FastImageViewWithUrl) ((ImageViewTarget) target).getView();
53
+ ThemedReactContext context = (ThemedReactContext) view.getContext();
54
+ RCTEventEmitter eventEmitter = context.getJSModule(RCTEventEmitter.class);
55
+ int viewId = view.getId();
56
+ eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_EVENT, mapFromResource(resource));
57
+ eventEmitter.receiveEvent(viewId, REACT_ON_LOAD_END_EVENT, new WritableNativeMap());
58
+ return false;
59
+ }
60
+ }
@@ -0,0 +1,112 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import android.content.Context;
4
+ import android.content.res.Resources;
5
+ import android.net.Uri;
6
+ import android.text.TextUtils;
7
+
8
+ import com.bumptech.glide.load.model.GlideUrl;
9
+ import com.bumptech.glide.load.model.Headers;
10
+ import com.facebook.react.views.imagehelper.ImageSource;
11
+
12
+ import javax.annotation.Nullable;
13
+
14
+ public class FastImageSource extends ImageSource {
15
+ private static final String DATA_SCHEME = "data";
16
+ private static final String LOCAL_RESOURCE_SCHEME = "res";
17
+ private static final String ANDROID_RESOURCE_SCHEME = "android.resource";
18
+ private static final String ANDROID_CONTENT_SCHEME = "content";
19
+ private static final String LOCAL_FILE_SCHEME = "file";
20
+ private final Headers mHeaders;
21
+ private Uri mUri;
22
+
23
+ public static boolean isBase64Uri(Uri uri) {
24
+ return DATA_SCHEME.equals(uri.getScheme());
25
+ }
26
+
27
+ public static boolean isLocalResourceUri(Uri uri) {
28
+ return LOCAL_RESOURCE_SCHEME.equals(uri.getScheme());
29
+ }
30
+
31
+ public static boolean isResourceUri(Uri uri) {
32
+ return ANDROID_RESOURCE_SCHEME.equals(uri.getScheme());
33
+ }
34
+
35
+ public static boolean isContentUri(Uri uri) {
36
+ return ANDROID_CONTENT_SCHEME.equals(uri.getScheme());
37
+ }
38
+
39
+ public static boolean isLocalFileUri(Uri uri) {
40
+ return LOCAL_FILE_SCHEME.equals(uri.getScheme());
41
+ }
42
+
43
+ public FastImageSource(Context context, String source) {
44
+ this(context, source, null);
45
+ }
46
+
47
+ public FastImageSource(Context context, String source, @Nullable Headers headers) {
48
+ this(context, source, 0.0d, 0.0d, headers);
49
+ }
50
+
51
+ public FastImageSource(Context context, String source, double width, double height, @Nullable Headers headers) {
52
+ super(context, source, width, height);
53
+ mHeaders = headers == null ? Headers.DEFAULT : headers;
54
+ mUri = super.getUri();
55
+
56
+ if (isResource() && TextUtils.isEmpty(mUri.toString())) {
57
+ throw new Resources.NotFoundException("Local Resource Not Found. Resource: '" + getSource() + "'.");
58
+ }
59
+
60
+ if (isLocalResourceUri(mUri)) {
61
+ // Convert res:/ scheme to android.resource:// so
62
+ // glide can understand the uri.
63
+ mUri = Uri.parse(mUri.toString().replace("res:/", ANDROID_RESOURCE_SCHEME + "://" + context.getPackageName() + "/"));
64
+ }
65
+ }
66
+
67
+
68
+ public boolean isBase64Resource() {
69
+ return mUri != null && FastImageSource.isBase64Uri(mUri);
70
+ }
71
+
72
+ public boolean isResource() {
73
+ return mUri != null && FastImageSource.isResourceUri(mUri);
74
+ }
75
+
76
+ public boolean isLocalFile() {
77
+ return mUri != null && FastImageSource.isLocalFileUri(mUri);
78
+ }
79
+
80
+ public boolean isContentUri() {
81
+ return mUri != null && FastImageSource.isContentUri(mUri);
82
+ }
83
+
84
+ public Object getSourceForLoad() {
85
+ if (isContentUri()) {
86
+ return getSource();
87
+ }
88
+ if (isBase64Resource()) {
89
+ return getSource();
90
+ }
91
+ if (isResource()) {
92
+ return getUri();
93
+ }
94
+ if (isLocalFile()) {
95
+ return getUri().toString();
96
+ }
97
+ return getGlideUrl();
98
+ }
99
+
100
+ @Override
101
+ public Uri getUri() {
102
+ return mUri;
103
+ }
104
+
105
+ public Headers getHeaders() {
106
+ return mHeaders;
107
+ }
108
+
109
+ public GlideUrl getGlideUrl() {
110
+ return new GlideUrl(getUri().toString(), getHeaders());
111
+ }
112
+ }
@@ -0,0 +1,153 @@
1
+ package com.dylanvann.fastimage;
2
+
3
+ import static com.bumptech.glide.request.RequestOptions.signatureOf;
4
+
5
+ import android.content.Context;
6
+ import android.graphics.Color;
7
+ import android.graphics.drawable.ColorDrawable;
8
+ import android.graphics.drawable.Drawable;
9
+ import android.widget.ImageView;
10
+ import android.widget.ImageView.ScaleType;
11
+
12
+ import com.bumptech.glide.Priority;
13
+ import com.bumptech.glide.load.engine.DiskCacheStrategy;
14
+ import com.bumptech.glide.load.model.Headers;
15
+ import com.bumptech.glide.load.model.LazyHeaders;
16
+ import com.bumptech.glide.request.RequestOptions;
17
+ import com.bumptech.glide.signature.ApplicationVersionSignature;
18
+ import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
19
+ import com.facebook.react.bridge.NoSuchKeyException;
20
+ import com.facebook.react.bridge.ReadableMap;
21
+ import com.facebook.react.bridge.ReadableMapKeySetIterator;
22
+
23
+ import java.util.HashMap;
24
+ import java.util.Map;
25
+
26
+ import javax.annotation.Nullable;
27
+
28
+ class FastImageViewConverter {
29
+ private static final Drawable TRANSPARENT_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
30
+
31
+ private static final Map<String, FastImageCacheControl> FAST_IMAGE_CACHE_CONTROL_MAP =
32
+ new HashMap<String, FastImageCacheControl>() {{
33
+ put("immutable", FastImageCacheControl.IMMUTABLE);
34
+ put("web", FastImageCacheControl.WEB);
35
+ put("cacheOnly", FastImageCacheControl.CACHE_ONLY);
36
+ }};
37
+
38
+ private static final Map<String, Priority> FAST_IMAGE_PRIORITY_MAP =
39
+ new HashMap<String, Priority>() {{
40
+ put("low", Priority.LOW);
41
+ put("normal", Priority.NORMAL);
42
+ put("high", Priority.HIGH);
43
+ }};
44
+
45
+ private static final Map<String, ImageView.ScaleType> FAST_IMAGE_RESIZE_MODE_MAP =
46
+ new HashMap<String, ImageView.ScaleType>() {{
47
+ put("contain", ScaleType.FIT_CENTER);
48
+ put("cover", ScaleType.CENTER_CROP);
49
+ put("stretch", ScaleType.FIT_XY);
50
+ put("center", ScaleType.CENTER_INSIDE);
51
+ }};
52
+
53
+ // Resolve the source uri to a file path that android understands.
54
+ static @Nullable
55
+ FastImageSource getImageSource(Context context, @Nullable ReadableMap source) {
56
+ return source == null
57
+ ? null
58
+ : new FastImageSource(context, source.getString("uri"), getHeaders(source));
59
+ }
60
+
61
+ static Headers getHeaders(ReadableMap source) {
62
+ Headers headers = Headers.DEFAULT;
63
+
64
+ if (source.hasKey("headers")) {
65
+ ReadableMap headersMap = source.getMap("headers");
66
+ ReadableMapKeySetIterator iterator = headersMap.keySetIterator();
67
+ LazyHeaders.Builder builder = new LazyHeaders.Builder();
68
+
69
+ while (iterator.hasNextKey()) {
70
+ String header = iterator.nextKey();
71
+ String value = headersMap.getString(header);
72
+
73
+ builder.addHeader(header, value);
74
+ }
75
+
76
+ headers = builder.build();
77
+ }
78
+
79
+ return headers;
80
+ }
81
+
82
+ static RequestOptions getOptions(Context context, FastImageSource imageSource, ReadableMap source) {
83
+ // Get priority.
84
+ final Priority priority = FastImageViewConverter.getPriority(source);
85
+ // Get cache control method.
86
+ final FastImageCacheControl cacheControl = FastImageViewConverter.getCacheControl(source);
87
+ DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.AUTOMATIC;
88
+ boolean onlyFromCache = false;
89
+ boolean skipMemoryCache = false;
90
+ switch (cacheControl) {
91
+ case WEB:
92
+ // If using none then OkHttp integration should be used for caching.
93
+ diskCacheStrategy = DiskCacheStrategy.NONE;
94
+ skipMemoryCache = true;
95
+ break;
96
+ case CACHE_ONLY:
97
+ onlyFromCache = true;
98
+ break;
99
+ case IMMUTABLE:
100
+ // Use defaults.
101
+ break;
102
+ }
103
+
104
+ RequestOptions options = new RequestOptions()
105
+ .diskCacheStrategy(diskCacheStrategy)
106
+ .onlyRetrieveFromCache(onlyFromCache)
107
+ .skipMemoryCache(skipMemoryCache)
108
+ .priority(priority)
109
+ .placeholder(TRANSPARENT_DRAWABLE);
110
+
111
+ if (imageSource.isResource()) {
112
+ // Every local resource (drawable) in Android has its own unique numeric id, which are
113
+ // generated at build time. Although these ids are unique, they are not guaranteed unique
114
+ // across builds. The underlying glide implementation caches these resources. To make
115
+ // sure the cache does not return the wrong image, we should clear the cache when the
116
+ // application version changes. Adding a cache signature for only these local resources
117
+ // solves this issue: https://github.com/DylanVann/react-native-fast-image/issues/402
118
+ options = options.apply(signatureOf(ApplicationVersionSignature.obtain(context)));
119
+ }
120
+
121
+ return options;
122
+ }
123
+
124
+ private static FastImageCacheControl getCacheControl(ReadableMap source) {
125
+ return getValueFromSource("cache", "immutable", FAST_IMAGE_CACHE_CONTROL_MAP, source);
126
+ }
127
+
128
+ private static Priority getPriority(ReadableMap source) {
129
+ return getValueFromSource("priority", "normal", FAST_IMAGE_PRIORITY_MAP, source);
130
+ }
131
+
132
+ static ScaleType getScaleType(String propValue) {
133
+ return getValue("resizeMode", "cover", FAST_IMAGE_RESIZE_MODE_MAP, propValue);
134
+ }
135
+
136
+ private static <T> T getValue(String propName, String defaultPropValue, Map<String, T> map, String propValue) {
137
+ if (propValue == null) propValue = defaultPropValue;
138
+ T value = map.get(propValue);
139
+ if (value == null)
140
+ throw new JSApplicationIllegalArgumentException("FastImage, invalid " + propName + " : " + propValue);
141
+ return value;
142
+ }
143
+
144
+ private static <T> T getValueFromSource(String propName, String defaultProp, Map<String, T> map, ReadableMap source) {
145
+ String propValue;
146
+ try {
147
+ propValue = source != null ? source.getString(propName) : null;
148
+ } catch (NoSuchKeyException e) {
149
+ propValue = null;
150
+ }
151
+ return getValue(propName, defaultProp, map, propValue);
152
+ }
153
+ }