@nativescript-community/ui-image 5.0.12 → 5.0.14

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.
@@ -13,13 +13,13 @@ import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
13
13
  import com.bumptech.glide.load.engine.cache.DiskCache;
14
14
  import com.bumptech.glide.load.engine.cache.DiskLruCacheWrapper;
15
15
  import com.bumptech.glide.load.engine.cache.MemoryCache;
16
- import com.bumptech.glide.load.engine.cache.LruResourceCache;
17
- import com.bumptech.glide.load.engine.CapturingEngineKeyFactory;
16
+ import com.bumptech.glide.load.engine.cache.ModelSignatureDiskLruCacheWrapper;
18
17
  import com.bumptech.glide.load.model.GlideUrl;
19
18
  import com.bumptech.glide.module.AppGlideModule;
20
19
  import com.bumptech.glide.RequestBuilder;
21
20
  import com.bumptech.glide.signature.ObjectKey;
22
21
  import okhttp3.OkHttpClient;
22
+ import java.io.File;
23
23
  import java.io.InputStream;
24
24
  import java.lang.reflect.Field;
25
25
  import java.lang.reflect.Modifier;
@@ -29,6 +29,37 @@ public class CustomGlideModule extends AppGlideModule {
29
29
  private static final String TAG = "MyAppGlideModule";
30
30
  private static final String INJECT_TAG = "EngineKeyFactoryInject";
31
31
 
32
+ private File getInternalCacheDirectory(@NonNull Context context, final String diskCacheName) {
33
+ File cacheDirectory = context.getCacheDir();
34
+ if (cacheDirectory == null) {
35
+ return null;
36
+ }
37
+ if (diskCacheName != null) {
38
+ return new File(cacheDirectory, diskCacheName);
39
+ }
40
+ return cacheDirectory;
41
+ }
42
+ public File getCacheDirectory(@NonNull Context context, final String diskCacheName) {
43
+ File internalCacheDirectory = getInternalCacheDirectory(context, diskCacheName);
44
+
45
+ // Already used internal cache, so keep using that one,
46
+ // thus avoiding using both external and internal with transient errors.
47
+ if (internalCacheDirectory != null && internalCacheDirectory.exists()) {
48
+ return internalCacheDirectory;
49
+ }
50
+
51
+ File cacheDirectory = context.getExternalCacheDir();
52
+
53
+ // Shared storage is not available.
54
+ if (cacheDirectory == null || !cacheDirectory.canWrite()) {
55
+ return internalCacheDirectory;
56
+ }
57
+ if (diskCacheName != null) {
58
+ return new File(cacheDirectory, diskCacheName);
59
+ }
60
+ return cacheDirectory;
61
+ }
62
+
32
63
  @Override
33
64
  public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
34
65
 
@@ -51,7 +82,7 @@ public class CustomGlideModule extends AppGlideModule {
51
82
  }
52
83
 
53
84
  // Use our custom memory cache wrapper
54
- LruResourceCache memoryCache = new LruResourceCache(memoryCacheSize);
85
+ ModelSignatureMemoryCache memoryCache = new ModelSignatureMemoryCache(memoryCacheSize);
55
86
  EvictionManager.get().setMemoryCache(memoryCache);
56
87
  builder.setMemoryCache(memoryCache);
57
88
 
@@ -60,7 +91,7 @@ public class CustomGlideModule extends AppGlideModule {
60
91
  builder.setDiskCache(new DiskCache.Factory() {
61
92
  @Override
62
93
  public DiskCache build() {
63
- DiskCache dc = DiskLruCacheWrapper.create(context.getCacheDir(), 250 * 1024 * 1024);
94
+ ModelSignatureDiskLruCacheWrapper dc = ModelSignatureDiskLruCacheWrapper.create(getCacheDirectory(context, config.getDiskCacheName()), config.getDiskCacheSize());
64
95
  EvictionManager.get().setDiskCache(dc);
65
96
  return dc;
66
97
  }
@@ -73,160 +104,10 @@ public class CustomGlideModule extends AppGlideModule {
73
104
  // Create base OkHttp client
74
105
  OkHttpClient client = new OkHttpClient.Builder().build();
75
106
 
76
- // SINGLE LOADER: CustomUrlLoader handles both CustomGlideUrl and GlideUrl
77
- // This replaces both the old CustomUrlLoader and UrlTrackingModelLoader
78
107
  registry.replace(
79
108
  GlideUrl.class,
80
109
  InputStream.class,
81
110
  new CustomUrlLoader.Factory(client));
82
- // Listener: called when an EngineKey is created. Update the stored keys to
83
- // include engineKey.
84
- CapturingEngineKeyFactory.Listener listener = (engineKey, model) -> {
85
- // Log.i("JS", "CapturingEngineKeyFactory.Listener 1" + engineKey + " " + model);
86
- if (model == null)
87
- return;
88
- String id = String.valueOf(model);
89
-
90
- // Read either persistent or in-memory stored keys
91
- CacheKeyStore.StoredKeys s = EvictionManager.get().getKeyStore().get(id);
92
- if (s == null) {
93
- // if key store exists but no entry, create minimal
94
- s = new CacheKeyStore.StoredKeys(
95
- new com.bumptech.glide.signature.ObjectKey(id),
96
- new com.bumptech.glide.signature.ObjectKey("signature-none"),
97
- com.bumptech.glide.request.target.Target.SIZE_ORIGINAL,
98
- com.bumptech.glide.request.target.Target.SIZE_ORIGINAL,
99
- null,
100
- null,
101
- android.graphics.Bitmap.class,
102
- new Options(),
103
- null,
104
- null);
105
- }
106
-
107
- // Build an updated StoredKeys that preserves everything and sets engineKey
108
- CacheKeyStore.StoredKeys updated = new CacheKeyStore.StoredKeys(
109
- s.sourceKey,
110
- s.signature,
111
- s.width,
112
- s.height,
113
- s.transformation, // may be null; preserved for in-process fallback
114
- s.transformationKeyBytes, // raw bytes if recorded (preferred)
115
- s.decodedResourceClass,
116
- s.options,
117
- s.optionsKeyBytes,
118
- engineKey // set the captured engineKey
119
- );
120
-
121
- // Put updated entry into the in-memory store so later EvictionManager can
122
- // remove memory entry.
123
- EvictionManager.get().getKeyStore().put(id, updated);
124
- };
125
-
126
- // Create the capturing factory
127
- // instantiate the capturing factory (public class in
128
- // com.bumptech.glide.load.engine)
129
- Object capturingFactory = new com.bumptech.glide.load.engine.CapturingEngineKeyFactory(listener);
130
-
131
- // inject it into Glide's Engine reflectively, passing it as Object (no
132
- // EngineKeyFactory compile-time ref)
133
- try {
134
- injectEngineKeyFactoryIntoGlide(glide, capturingFactory);
135
- Log.i(TAG, "Injected capturing EngineKeyFactory into Glide engine");
136
- } catch (Exception e) {
137
- Log.w(TAG, "Failed to inject capturing EngineKeyFactory", e);
138
- }
139
-
140
- }
141
-
142
- /**
143
- * Reflectively find Glide.engine and replace its EngineKeyFactory-typed field
144
- * with capturingFactory.
145
- * This tries to be resilient across minor Glide 5.x binary differences.
146
- */
147
- private void injectEngineKeyFactoryIntoGlide(Object glideInstance, Object capturingFactory) throws Exception {
148
- if (glideInstance == null) {
149
- throw new IllegalArgumentException("glideInstance == null");
150
- }
151
- // 1) find Engine field on Glide
152
- Field engineField = null;
153
- for (Field f : glideInstance.getClass().getDeclaredFields()) {
154
- if (f.getType().getName().contains("Engine")) {
155
- engineField = f;
156
- break;
157
- }
158
- }
159
- if (engineField == null) {
160
- throw new NoSuchFieldException("Could not find Engine field on Glide");
161
- }
162
- engineField.setAccessible(true);
163
- Object engineInstance = engineField.get(glideInstance);
164
- if (engineInstance == null) {
165
- throw new IllegalStateException("Glide.engine is null");
166
- }
167
-
168
- // 2) find the keyFactory-like field on Engine
169
- Field targetField = null;
170
- Class<?> engineClass = engineInstance.getClass();
171
- Class<?> cur = engineClass;
172
- while (cur != null && targetField == null) {
173
- for (Field f : cur.getDeclaredFields()) {
174
- String typeName = f.getType().getName();
175
- if (typeName.contains("EngineKeyFactory") || typeName.endsWith("EngineKeyFactory")
176
- || f.getName().toLowerCase().contains("keyfactory")) {
177
- targetField = f;
178
- break;
179
- }
180
- }
181
- cur = cur.getSuperclass();
182
- }
183
- if (targetField == null) {
184
- throw new NoSuchFieldException(
185
- "Could not find EngineKeyFactory-like field in Engine class: " + engineClass.getName());
186
- }
187
-
188
- targetField.setAccessible(true);
189
-
190
- // Log current value
191
- Object before = targetField.get(engineInstance);
192
- int beforeHash = System.identityHashCode(before);
193
- String beforeClass = (before == null) ? "null" : before.getClass().getName();
194
-
195
- // If field is final, try to remove final modifier so setting works reliably
196
- try {
197
- Field modifiersField = Field.class.getDeclaredField("modifiers");
198
- modifiersField.setAccessible(true);
199
- int mods = targetField.getModifiers();
200
- if (Modifier.isFinal(mods)) {
201
- modifiersField.setInt(targetField, mods & ~Modifier.FINAL);
202
- }
203
- } catch (NoSuchFieldException nsf) {
204
- // Android ART may not expose 'modifiers' the same way; ignore if not available
205
- Log.i(INJECT_TAG, "Could not access Field.modifiers to clear final; continuing");
206
- } catch (Throwable t) {
207
- Log.w(INJECT_TAG, "Failed to clear final modifier (continuing attempt to set field)", t);
208
- }
209
-
210
- // 3) set the new factory instance
211
- try {
212
- targetField.set(engineInstance, capturingFactory);
213
- } catch (IllegalAccessException | IllegalArgumentException iae) {
214
- // Log and rethrow so caller can inspect
215
- Log.w(INJECT_TAG, "targetField.set(...) failed", iae);
216
- throw iae;
217
- }
218
-
219
- // 4) read back and log to verify
220
- Object after = targetField.get(engineInstance);
221
- int afterHash = System.identityHashCode(after);
222
- String afterClass = (after == null) ? "null" : after.getClass().getName();
223
-
224
- // quick verification: are they the same instance we tried to set?
225
- boolean sameInstance = (after == capturingFactory);
226
- if (!sameInstance) {
227
- throw new IllegalStateException(
228
- "Injection did not set the expected capturingFactory instance. afterClass=" + afterClass);
229
- }
230
111
  }
231
112
 
232
113
  @Override
@@ -2,6 +2,7 @@ package com.nativescript.image;
2
2
 
3
3
  import com.bumptech.glide.load.model.GlideUrl;
4
4
  import com.bumptech.glide.load.model.LazyHeaders;
5
+ import com.bumptech.glide.load.model.Headers;
5
6
  import java.util.Map;
6
7
 
7
8
  /**
@@ -16,8 +17,7 @@ public class CustomGlideUrl extends GlideUrl {
16
17
  Map<String, String> headers,
17
18
  ImageProgressCallback progressCallback,
18
19
  ImageLoadSourceCallback loadSourceCallback) {
19
- // Use LazyHeaders.Builder - Glide automatically includes these in cache key!
20
- super(url, buildLazyHeaders(headers));
20
+ super(url, headers != null ? buildLazyHeaders(headers) : Headers.DEFAULT);
21
21
  this.progressCallback = progressCallback;
22
22
  this.loadSourceCallback = loadSourceCallback;
23
23
  }