@nativescript-community/ui-image 4.6.6 → 5.0.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 (55) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +4 -20
  3. package/index-common.d.ts +47 -18
  4. package/index-common.js +5 -69
  5. package/index-common.js.map +1 -1
  6. package/index.android.d.ts +33 -60
  7. package/index.android.js +597 -702
  8. package/index.android.js.map +1 -1
  9. package/index.d.ts +17 -92
  10. package/index.ios.d.ts +5 -10
  11. package/index.ios.js +72 -54
  12. package/index.ios.js.map +1 -1
  13. package/package.json +4 -4
  14. package/platforms/android/include.gradle +21 -16
  15. package/platforms/android/java/com/nativescript/image/CacheKeyStore.java +65 -0
  16. package/platforms/android/java/com/nativescript/image/CapturingEngineKeyFactory.java +43 -0
  17. package/platforms/android/java/com/nativescript/image/CompositeRequestListener.java +58 -0
  18. package/platforms/android/java/com/nativescript/image/ConditionalCrossFadeFactory.java +33 -0
  19. package/platforms/android/java/com/nativescript/image/CustomDataFetcher.java +124 -0
  20. package/platforms/android/java/com/nativescript/image/CustomGlideModule.java +220 -0
  21. package/platforms/android/java/com/nativescript/image/CustomGlideUrl.java +52 -0
  22. package/platforms/android/java/com/nativescript/image/CustomUrlLoader.java +74 -0
  23. package/platforms/android/java/com/nativescript/image/EvictionManager.java +735 -0
  24. package/platforms/android/java/com/nativescript/image/ExtractRequestOptions.java +109 -0
  25. package/platforms/android/java/com/nativescript/image/ImageLoadSourceCallback.java +5 -0
  26. package/platforms/android/java/com/nativescript/image/ImageProgressCallback.java +5 -0
  27. package/platforms/android/java/com/nativescript/image/LoadSourceInterceptor.java +28 -0
  28. package/platforms/android/java/com/nativescript/image/MatrixDrawable.java +200 -0
  29. package/platforms/android/java/com/nativescript/image/MatrixDrawableImageViewTarget.java +154 -0
  30. package/platforms/android/java/com/nativescript/image/MatrixImageView.java +696 -0
  31. package/platforms/android/java/com/nativescript/image/ProgressInterceptor.java +25 -0
  32. package/platforms/android/java/com/nativescript/image/ProgressResponseBody.java +70 -0
  33. package/platforms/android/java/com/nativescript/image/RecordingDigest.java +48 -0
  34. package/platforms/android/java/com/nativescript/image/RecreatedResourceKey.java +95 -0
  35. package/platforms/android/java/com/nativescript/image/SaveKeysRequestListener.java +145 -0
  36. package/platforms/android/java/com/nativescript/image/ScaleUtils.java +129 -0
  37. package/platforms/android/java/com/nativescript/image/SharedPrefCacheKeyStore.java +92 -0
  38. package/platforms/android/native-api-usage.json +39 -37
  39. package/platforms/ios/Podfile +1 -1
  40. package/references.d.ts +0 -1
  41. package/tsconfig.tsbuildinfo +1 -1
  42. package/typings/android.d.ts +4 -27
  43. package/typings/glide.android.d.ts +9395 -0
  44. package/typings/glide.okhttp.android.d.ts +104 -0
  45. package/typings/glide.transform.android.d.ts +540 -0
  46. package/typings/ui_image.android.d.ts +517 -0
  47. package/platforms/android/java/com/nativescript/image/BaseDataSubscriber.java +0 -22
  48. package/platforms/android/java/com/nativescript/image/BaseDataSubscriberListener.java +0 -9
  49. package/platforms/android/java/com/nativescript/image/DraweeView.java +0 -371
  50. package/platforms/android/java/com/nativescript/image/NetworkImageRequest.java +0 -55
  51. package/platforms/android/java/com/nativescript/image/OkHttpNetworkFetcher.java +0 -56
  52. package/platforms/android/java/com/nativescript/image/ScalingBlurPostprocessor.java +0 -64
  53. package/platforms/android/java/com/nativescript/image/ScalingUtils.java +0 -519
  54. package/typings/fresco-processors.d.ts +0 -53
  55. package/typings/fresco.d.ts +0 -12070
@@ -0,0 +1,109 @@
1
+ package com.nativescript.image;
2
+
3
+ import android.util.Log;
4
+ import com.bumptech.glide.load.Options;
5
+ import com.bumptech.glide.request.RequestOptions;
6
+ import java.lang.reflect.Field;
7
+ import java.lang.reflect.Method;
8
+
9
+ /**
10
+ * Utility to extract com.bumptech.glide.load.Options from a RequestOptions
11
+ * instance via reflection.
12
+ *
13
+ * Behavior:
14
+ * - Try public RequestOptions.getOptions() if present (cached).
15
+ * - Otherwise try to find a private 'options' field on RequestOptions or its
16
+ * superclasses (cached).
17
+ * - If neither is found, return new Options() and log a single warning
18
+ * (subsequent calls won't re-log lookup failures).
19
+ *
20
+ * Notes:
21
+ * - Reflection is fragile across Glide versions and with R8/ProGuard. This
22
+ * class logs failures and falls back safely.
23
+ */
24
+ public final class ExtractRequestOptions {
25
+ private static final String TAG = "ExtractRequestOptions";
26
+
27
+ // Cached reflective handles and lookup state
28
+ private static volatile Method cachedGetOptionsMethod;
29
+ private static volatile Field cachedOptionsField;
30
+ private static volatile boolean triedMethodLookup = false;
31
+ private static volatile boolean triedFieldLookup = false;
32
+
33
+ private ExtractRequestOptions() {
34
+ }
35
+
36
+ /**
37
+ * Extracts the internal Options from a RequestOptions instance.
38
+ * This method is fast after the first call because it caches reflective
39
+ * handles.
40
+ */
41
+ public static Options getFrom(RequestOptions requestOptions) {
42
+ if (requestOptions == null) {
43
+ return new Options();
44
+ }
45
+
46
+ // 2) Try cached field lookup if method didn't yield a result
47
+ Field f = cachedOptionsField;
48
+ if (f == null && !triedFieldLookup) {
49
+ synchronized (ExtractRequestOptions.class) {
50
+ if (!triedFieldLookup) {
51
+ triedFieldLookup = true;
52
+ Class<?> cls = requestOptions.getClass();
53
+ while (cls != null && cls != Object.class) {
54
+ try {
55
+ Field optionsField = cls.getDeclaredField("options");
56
+ if (optionsField != null) {
57
+ optionsField.setAccessible(true);
58
+ cachedOptionsField = optionsField;
59
+ f = optionsField;
60
+ break;
61
+ }
62
+ } catch (NoSuchFieldException nsf) {
63
+ // try superclass
64
+ cls = cls.getSuperclass();
65
+ } catch (Throwable t) {
66
+ Log.w(TAG, "Failed to access 'options' field via reflection", t);
67
+ break;
68
+ }
69
+ }
70
+ if (f == null) {
71
+ Log.w(TAG, "Could not find 'options' field on RequestOptions (will fall back to new Options()).");
72
+ }
73
+ } else {
74
+ f = cachedOptionsField;
75
+ }
76
+ }
77
+ }
78
+
79
+ if (f != null) {
80
+ try {
81
+ Object value = f.get(requestOptions);
82
+ if (value instanceof Options) {
83
+ return (Options) value;
84
+ } else {
85
+ Log.w(TAG, "Found 'options' field but it's not an Options instance: "
86
+ + (value == null ? "null" : value.getClass().getName()));
87
+ }
88
+ } catch (Throwable t) {
89
+ Log.w(TAG, "Reading cached 'options' field failed; falling back to new Options()", t);
90
+ }
91
+ }
92
+ // 3) Final fallback: return new Options() and warn (only logged during the
93
+ // first failed lookups)
94
+ return new Options();
95
+ }
96
+
97
+ /**
98
+ * Optional: clear cached reflective handles. Useful for tests or if you load
99
+ * different Glide versions at runtime.
100
+ */
101
+ public static void clearCache() {
102
+ synchronized (ExtractRequestOptions.class) {
103
+ cachedGetOptionsMethod = null;
104
+ cachedOptionsField = null;
105
+ triedMethodLookup = false;
106
+ triedFieldLookup = false;
107
+ }
108
+ }
109
+ }
@@ -0,0 +1,5 @@
1
+ package com.nativescript.image;
2
+
3
+ public interface ImageLoadSourceCallback {
4
+ void onLoadStarted(String url, String source); // "network"
5
+ }
@@ -0,0 +1,5 @@
1
+ package com.nativescript.image;
2
+
3
+ public interface ImageProgressCallback {
4
+ void onProgress(String url, long bytesRead, long totalBytes);
5
+ }
@@ -0,0 +1,28 @@
1
+ package com.nativescript.image;
2
+
3
+ import java.io.IOException;
4
+ import okhttp3.Interceptor;
5
+ import okhttp3.Response;
6
+
7
+ public class LoadSourceInterceptor implements Interceptor {
8
+ private final String url;
9
+ private final ImageLoadSourceCallback callback;
10
+ private boolean notified = false;
11
+
12
+ public LoadSourceInterceptor(String url, ImageLoadSourceCallback callback) {
13
+ this.url = url;
14
+ this.callback = callback;
15
+ }
16
+
17
+ @Override
18
+ public Response intercept(Chain chain) throws IOException {
19
+ // Notify that network load is starting BEFORE making the request
20
+ if (!notified && callback != null) {
21
+ callback.onLoadStarted(url, "network");
22
+ notified = true;
23
+ }
24
+
25
+ // Proceed with the request
26
+ return chain.proceed(chain.request());
27
+ }
28
+ }
@@ -0,0 +1,200 @@
1
+ package com.nativescript.image;
2
+
3
+ import android.graphics.Canvas;
4
+ import android.graphics.Matrix;
5
+ import android.graphics.Outline;
6
+ import android.graphics.Rect;
7
+ import android.graphics.drawable.Animatable;
8
+ import android.graphics.drawable.Drawable;
9
+
10
+ import androidx.annotation.NonNull;
11
+ import androidx.annotation.Nullable;
12
+
13
+ /**
14
+ * Drawable wrapper that applies a Matrix before drawing the wrapped drawable
15
+ * and
16
+ * properly forwards drawable callbacks so animated drawables work.
17
+ *
18
+ * Behavior:
19
+ * - The wrapped drawable is kept in drawable-local coords: bounds
20
+ * (0,0,intrinsicW,intrinsicH).
21
+ * - setMatrix(matrix) expects a matrix mapping drawable-local coords -> view
22
+ * coords.
23
+ * - We implement Drawable.Callback methods
24
+ * (invalidateDrawable/scheduleDrawable/unscheduleDrawable)
25
+ * so the wrapped drawable can drive invalidation/scheduling through this
26
+ * wrapper.
27
+ *
28
+ * Notes:
29
+ * - Drawable.setCallback(...) is final on some Android versions and cannot be
30
+ * overridden.
31
+ * We therefore ensure the wrapped drawable's callback points at this wrapper by
32
+ * calling
33
+ * mWrapped.setCallback(this) in the constructor and expose
34
+ * refreshWrappedCallback()
35
+ * so hosts can re-assert the relationship if needed (e.g. after ImageView
36
+ * changes state).
37
+ */
38
+ public class MatrixDrawable extends Drawable implements Drawable.Callback, Animatable {
39
+
40
+ private final Drawable mWrapped;
41
+ private final Matrix mMatrix = new Matrix();
42
+ private final Rect mViewBounds = new Rect();
43
+
44
+ public MatrixDrawable(@NonNull Drawable wrapped) {
45
+ mWrapped = wrapped;
46
+ int iw = Math.max(1, wrapped.getIntrinsicWidth());
47
+ int ih = Math.max(1, wrapped.getIntrinsicHeight());
48
+ // Keep wrapped drawable in drawable-local coordinates:
49
+ mWrapped.setBounds(0, 0, iw, ih);
50
+ // Ensure wrapped drawable callbacks are delivered to this wrapper
51
+ mWrapped.setCallback(this);
52
+ }
53
+
54
+ /**
55
+ * Re-assert that the wrapped drawable's callback is this wrapper.
56
+ * Call this if you suspect the wrapped drawable's callback may have been
57
+ * changed.
58
+ */
59
+ public void refreshWrappedCallback() {
60
+ mWrapped.setCallback(this);
61
+ }
62
+
63
+ /**
64
+ * Set the transformation matrix that maps the wrapped drawable coordinates
65
+ * into this drawable's view coordinates. Pass null to reset to identity.
66
+ */
67
+ public void setMatrix(@Nullable Matrix matrix) {
68
+ mMatrix.reset();
69
+ if (matrix != null) {
70
+ mMatrix.set(matrix);
71
+ }
72
+ invalidateSelf();
73
+ }
74
+
75
+ @Override
76
+ public void draw(@NonNull Canvas canvas) {
77
+ int save = canvas.save();
78
+ // Apply the matrix that maps drawable-local coords -> view coords.
79
+ canvas.concat(mMatrix);
80
+ // Draw the wrapped drawable which is in drawable-local coords.
81
+ mWrapped.draw(canvas);
82
+ canvas.restoreToCount(save);
83
+ }
84
+
85
+ @Override
86
+ public void setAlpha(int alpha) {
87
+ mWrapped.setAlpha(alpha);
88
+ }
89
+
90
+ @Override
91
+ public void setColorFilter(@Nullable android.graphics.ColorFilter colorFilter) {
92
+ mWrapped.setColorFilter(colorFilter);
93
+ }
94
+
95
+ @Override
96
+ public int getOpacity() {
97
+ return mWrapped.getOpacity();
98
+ }
99
+
100
+ @Override
101
+ public void setBounds(int left, int top, int right, int bottom) {
102
+ // Bounds here represent the view bounds. Keep them for invalidation and
103
+ // measurement,
104
+ // but the wrapped drawable remains in drawable-local coords.
105
+ super.setBounds(left, top, right, bottom);
106
+ mViewBounds.set(left, top, right, bottom);
107
+
108
+ // ensure wrapped drawable remains in drawable-local coords
109
+ int iw = mWrapped.getIntrinsicWidth();
110
+ int ih = mWrapped.getIntrinsicHeight();
111
+ if (iw <= 0)
112
+ iw = 1;
113
+ if (ih <= 0)
114
+ ih = 1;
115
+ mWrapped.setBounds(0, 0, iw, ih);
116
+ }
117
+
118
+ @Override
119
+ protected void onBoundsChange(Rect bounds) {
120
+ super.onBoundsChange(bounds);
121
+ mViewBounds.set(bounds);
122
+ }
123
+
124
+ @Override
125
+ public int getIntrinsicWidth() {
126
+ return mWrapped.getIntrinsicWidth();
127
+ }
128
+
129
+ @Override
130
+ public int getIntrinsicHeight() {
131
+ return mWrapped.getIntrinsicHeight();
132
+ }
133
+
134
+ @Override
135
+ public void getOutline(@NonNull Outline outline) {
136
+ // Optional: forward to wrapped drawable's outline if desired. Default behavior
137
+ // left empty.
138
+ // If you want the wrapper to provide the wrapped outline, uncomment the next
139
+ // line:
140
+ // mWrapped.getOutline(outline);
141
+ super.getOutline(outline);
142
+ }
143
+
144
+ // Drawable.Callback implementations: forward wrapped callbacks to the wrapper
145
+ // host
146
+
147
+ @Override
148
+ public void invalidateDrawable(@NonNull Drawable who) {
149
+ // When wrapped drawable requests invalidation, propagate invalidation of this
150
+ // wrapper.
151
+ invalidateSelf();
152
+ }
153
+
154
+ @Override
155
+ public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) {
156
+ // Forward scheduling to this drawable's callback (typically the View)
157
+ final Drawable.Callback cb = getCallback();
158
+ if (cb != null) {
159
+ cb.scheduleDrawable(this, what, when);
160
+ }
161
+ }
162
+
163
+ @Override
164
+ public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
165
+ final Drawable.Callback cb = getCallback();
166
+ if (cb != null) {
167
+ cb.unscheduleDrawable(this, what);
168
+ }
169
+ }
170
+
171
+ // Animatable forwarding so callers can treat MatrixDrawable as animatable when
172
+ // wrapped drawable is
173
+ @Override
174
+ public void start() {
175
+ if (mWrapped instanceof Animatable) {
176
+ ((Animatable) mWrapped).start();
177
+ }
178
+ }
179
+
180
+ @Override
181
+ public void stop() {
182
+ if (mWrapped instanceof Animatable) {
183
+ ((Animatable) mWrapped).stop();
184
+ }
185
+ }
186
+
187
+ @Override
188
+ public boolean isRunning() {
189
+ return (mWrapped instanceof Animatable) && ((Animatable) mWrapped).isRunning();
190
+ }
191
+
192
+ @Override
193
+ public boolean setVisible(boolean visible, boolean restart) {
194
+ boolean changed = super.setVisible(visible, restart);
195
+ // forward visibility to wrapped drawable so animations can start/stop
196
+ // appropriately
197
+ mWrapped.setVisible(visible, restart);
198
+ return changed;
199
+ }
200
+ }
@@ -0,0 +1,154 @@
1
+ package com.nativescript.image;
2
+
3
+ import android.graphics.drawable.Animatable;
4
+ import android.graphics.drawable.Drawable;
5
+ import android.widget.ImageView;
6
+ import androidx.annotation.NonNull;
7
+ import androidx.annotation.Nullable;
8
+ import com.bumptech.glide.request.target.ViewTarget;
9
+ import com.bumptech.glide.request.transition.Transition;
10
+
11
+ /**
12
+ * Glide target that doesn't clear/replace the ImageView if the placeholder is
13
+ * null.
14
+ * This avoids a transient "blank" state when a Glide request starts without a
15
+ * placeholder.
16
+ */
17
+ public class MatrixDrawableImageViewTarget extends ViewTarget<ImageView, Drawable>
18
+ implements Transition.ViewAdapter {
19
+
20
+ @Nullable
21
+ private Animatable animatable;
22
+
23
+ public MatrixDrawableImageViewTarget(ImageView view) {
24
+ super(view);
25
+ }
26
+
27
+ /**
28
+ * @deprecated Use {@link #waitForLayout()} instead.
29
+ */
30
+ @SuppressWarnings({"deprecation"})
31
+ @Deprecated
32
+ public MatrixDrawableImageViewTarget(ImageView view, boolean waitForLayout) {
33
+ super(view, waitForLayout);
34
+ }
35
+
36
+ /**
37
+ * Returns the current {@link android.graphics.drawable.Drawable} being
38
+ * displayed in the view
39
+ * using {@link android.widget.ImageView#getDrawable()}.
40
+ */
41
+ @Override
42
+ @Nullable
43
+ public Drawable getCurrentDrawable() {
44
+ return view.getDrawable();
45
+ }
46
+
47
+ /**
48
+ * Sets the given {@link android.graphics.drawable.Drawable} on the view using
49
+ * {@link
50
+ * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
51
+ *
52
+ * @param drawable {@inheritDoc}
53
+ */
54
+ @Override
55
+ public void setDrawable(Drawable drawable) {
56
+ view.setImageDrawable(drawable);
57
+ }
58
+
59
+ /**
60
+ * Sets the given {@link android.graphics.drawable.Drawable} on the view using
61
+ * {@link
62
+ * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
63
+ *
64
+ * @param placeholder {@inheritDoc}
65
+ */
66
+ @Override
67
+ public void onLoadStarted(@Nullable Drawable placeholder) {
68
+ super.onLoadStarted(placeholder);
69
+
70
+ // setResourceInternal(null);
71
+ if (placeholder != null) {
72
+ setDrawable(placeholder);
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Sets the given {@link android.graphics.drawable.Drawable} on the view using
78
+ * {@link
79
+ * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
80
+ *
81
+ * @param errorDrawable {@inheritDoc}
82
+ */
83
+ @Override
84
+ public void onLoadFailed(@Nullable Drawable errorDrawable) {
85
+ super.onLoadFailed(errorDrawable);
86
+ setResourceInternal(null);
87
+ if (errorDrawable != null) {
88
+ setDrawable(errorDrawable);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Sets the given {@link android.graphics.drawable.Drawable} on the view using
94
+ * {@link
95
+ * android.widget.ImageView#setImageDrawable(android.graphics.drawable.Drawable)}.
96
+ *
97
+ * @param placeholder {@inheritDoc}
98
+ */
99
+ @Override
100
+ public void onLoadCleared(@Nullable Drawable placeholder) {
101
+ super.onLoadCleared(placeholder);
102
+ if (animatable != null) {
103
+ animatable.stop();
104
+ }
105
+ // setResourceInternal(null);
106
+ if (placeholder != null) {
107
+ setDrawable(placeholder);
108
+ }
109
+ }
110
+
111
+ @Override
112
+ public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
113
+ if (transition == null || !transition.transition(resource, this)) {
114
+ setResourceInternal(resource);
115
+ } else {
116
+ maybeUpdateAnimatable(resource);
117
+ }
118
+ }
119
+
120
+ @Override
121
+ public void onStart() {
122
+ if (animatable != null) {
123
+ animatable.start();
124
+ }
125
+ }
126
+
127
+ @Override
128
+ public void onStop() {
129
+ if (animatable != null) {
130
+ animatable.stop();
131
+ }
132
+ }
133
+
134
+ private void setResourceInternal(@Nullable Drawable resource) {
135
+ // Order matters here. Set the resource first to make sure that the Drawable has
136
+ // a valid and
137
+ // non-null Callback before starting it.
138
+ setResource(resource);
139
+ maybeUpdateAnimatable(resource);
140
+ }
141
+
142
+ private void maybeUpdateAnimatable(@Nullable Drawable resource) {
143
+ if (resource instanceof Animatable) {
144
+ animatable = (Animatable) resource;
145
+ animatable.start();
146
+ } else {
147
+ animatable = null;
148
+ }
149
+ }
150
+
151
+ protected void setResource(@Nullable Drawable resource) {
152
+ view.setImageDrawable(resource);
153
+ }
154
+ }