diff --git a/BlastedImage.podspec b/BlastedImage.podspec
index 4ec1a75..5ed1c69 100644
--- a/BlastedImage.podspec
+++ b/BlastedImage.podspec
@@ -19,5 +19,7 @@ Pod::Spec.new do |s|
s.dependency "React-Core"
s.dependency "SDWebImage"
+ s.dependency "SDWebImageSVGCoder"
+ s.dependency 'SDWebImageAVIFCoder'
end
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f6f6ba..153aa02 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,37 @@
-## [1.0.8] (2025-01-12)
+## [1.1.0] (2025-01-31)
+
+#### 🚨 Breaking Changes (Android Only)
+- **Upgraded Glide from 4.12.0 to 4.16.0** which may cause duplicate class conflicts if another package in your project also includes Glide.
+
+If you encounter a build error stating `com.bumptech.glide.GeneratedAppGlideModuleImpl is defined multiple times` it means another package in your project is also bundling Glide.
+
+To resolve this check the error message for the conflicting package and remove it if not needed.
+
+Alternatively ensure all dependencies use the same Glide version by adding the following to your android/app/build.gradle file:
+```
+dependencies {
+ implementation 'com.github.bumptech.glide:glide:4.16.0'
+}
+```
+#### ✨ New Features
+
+- Added support for returning image dimensions via `onLoad` in combination by setting the `returnSize` param. ([#32](https://github.com/xerdnu/react-native-blasted-image/issues/32))
+- Added support for `SVG` images.
+- Added support for `AVIF` images. ([#20](https://github.com/xerdnu/react-native-blasted-image/issues/20))
+- Added support for changing color with `tintColor` parameter. ([#11](https://github.com/xerdnu/react-native-blasted-image/issues/11))
+
+#### 🔥 Improvements
+
+- Reworked parts of the code and created renderKey that will make sure images that failed in retry operation re-renders. ([#31](https://github.com/xerdnu/react-native-blasted-image/issues/31))
+- Reworked other parts of the code for increased performance.
+
+#### 🔄 Changes
+
+- Updated documentation.
+- Changed repo for Android buildscript.
+- Increased caching limits.
+
+## [1.0.9] (2025-01-12)
#### New Features
@@ -223,6 +256,7 @@
- Initial release.
+[1.1.0]: https://github.com/xerdnu/react-native-blasted-image/compare/v1.0.9...v1.1.0
[1.0.9]: https://github.com/xerdnu/react-native-blasted-image/compare/v1.0.8...v1.0.9
[1.0.8]: https://github.com/xerdnu/react-native-blasted-image/compare/v1.0.7...v1.0.8
[1.0.7]: https://github.com/xerdnu/react-native-blasted-image/compare/v1.0.6...v1.0.7
diff --git a/README.md b/README.md
index 008dd5f..b84d082 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,15 @@
A simple yet powerful image component for React Native, powered by [Glide](https://github.com/bumptech/glide) (Android) and [SDWebImage](https://github.com/SDWebImage/SDWebImage) (iOS).
+## Support My Work! 🎉
+I truly appreciate your support! If you'd like to help me out, the best way is to check out my latest app — **LogoDuel**.
+
+**LogoDuel** is a fun, turn-based multiplayer trivia game where you challenge friends (or foes!) to guess famous logos. Test your brand knowledge and see who comes out on top!
+
+🚀 **Powered by BlastedImage** for performant and optimized image handling.
👉 Download now and let the logo battle begin!
+
+[![Get it on Google Play](https://img.shields.io/badge/Google_Play-Download-green?logo=google-play&style=for-the-badge)](https://play.google.com/store/apps/details?id=se.netblast.logoduellen) [![Download on the App Store](https://img.shields.io/badge/App_Store-Download-blue?logo=apple&style=for-the-badge)](https://apps.apple.com/us/app/logoduel/id6470379520)
+
## Description
Caching remote images has always been a challenge for me with the Image component in React Native. This simplified, yet powerful component, addresses that issue head-on. It offers a robust and performant mechanism for caching remote images, ensuring they're displayed quickly.
Leveraging the strengths of Glide and SDWebImage, it supports both memory and disk caching for remote images. The newly added Hybrid Assets feature allows you to bundle remote assets in your build, fetching from the network only when necessary. Notably, while it provides these enhanced capabilities for remote images, it seamlessly integrates with the standard React Native Image component when handling local assets using require.
@@ -16,6 +25,20 @@ Caching remote images has always been a challenge for me with the Image componen
- **Robust Caching**: Benefits from both memory and disk caching for maximum performance.
- **Hybrid Assets**: Bundle remote assets within your build and only fetch from the network if assets are not included.
+## Supported Image Types
+
+| Filetype | Android | iOS |
+| :--------: | :-----: | :-: |
+|PNG|✅|✅|
+|APNG|✅|✅|
+|JPEG|✅|✅|
+|SVG|✅|✅|
+|GIF|✅|✅|
+|WebP|✅|✅|
+|AVIF|✅|✅|
+|HEIC|✅|✅|
+|ICO|✅|✅|
+
## Installation
### With bare React Native
#### Using npm:
@@ -59,11 +82,13 @@ import BlastedImage from 'react-native-blasted-image';
| `height` | `Number` | (Optional) Specifies the height of the image. `Overrides height in style` | 100 |
| `resizeMode` | `String` | (Optional) Resize the image with one of the options: `cover` `contain` `center` `stretch` | cover |
| `isBackground` | `Boolean` | (Optional) Makes the image act as a container background similar to the native `ImageBackground` component | false |
-| `fallbackSource` | `Object` | (Optional) Object containing a `uri` string for a custom error image. | - |
+| `returnSize` | `Boolean` | (Optional) Specifies if `Size` parameters should be returned in `onLoad` callback. | false |
| `retries` | `Number` | (Optional) Specifies the number of retry attempts if the image fails to load. | 3 |
-| `onLoad` | `Function` | (Optional) Callback function that gets called when the image has loaded succesfully. | - |
+| `tintColor` | `String` | (Optional) Specifies tintColor for the image using hexadecimal/named colors. | - |
+| `fallbackSource` | `Object` | (Optional) Object containing a `uri` string for a custom error image. | - |
+| `onLoad` | `Function` | (Optional) Callback function that gets called when the image has loaded succesfully. Returns `Size` parameters of the source image if `returnSize` set to `true` | - |
| `onError` | `Function` | (Optional) Callback function that gets called when there was an error loading the image. | - |
-| `style` | `Object` | (Optional) Styles to be applied to the image, e.g., `{borderRadius:20}`. See [View Style Props](https://reactnative.dev/docs/view-style-props) for all available styles.
+| `style` | `Object` | (Optional) Styles to be applied to the image, e.g., `{borderRadius:20}`. See [View Style Props](https://reactnative.dev/docs/view-style-props) for all available styles.
### Source Parameter
| Parameter | Type | Description | Default |
|--------------|-------------------|-----------------------------------------------------------------------------------------------------|---------|
@@ -176,11 +201,11 @@ useEffect(() => {
This component was created with inspiration from [react-native-fast-image](https://github.com/DylanVann/react-native-fast-image) that also uses [Glide](https://github.com/bumptech/glide) and [SDWebImage](https://github.com/SDWebImage/SDWebImage). But due to its lack of ongoing maintenance i felt the need to develop this new image component to continue providing robust and performant caching functionality.
## Support My Work! 🎉
-I truly appreciate your support! If you'd like to help me out, the best way is to check out my latest app — LogoDuel.
+I truly appreciate your support! If you'd like to help me out, the best way is to check out my latest app — **LogoDuel**.
-LogoDuel is a fun, fast-paced multiplayer trivia game where you challenge friends (or foes!) to guess famous logos. Test your brand knowledge and see who comes out on top!
+**LogoDuel** is a fun, turn-based multiplayer trivia game where you challenge friends (or foes!) to guess famous logos. Test your brand knowledge and see who comes out on top!
-👉 Download now and let the logo battle begin!
+🚀 **Powered by BlastedImage** for performant and optimized image handling.
👉 Download now and let the logo battle begin!
[![Get it on Google Play](https://img.shields.io/badge/Google_Play-Download-green?logo=google-play&style=for-the-badge)](https://play.google.com/store/apps/details?id=se.netblast.logoduellen) [![Download on the App Store](https://img.shields.io/badge/App_Store-Download-blue?logo=apple&style=for-the-badge)](https://apps.apple.com/us/app/logoduel/id6470379520)
diff --git a/android/build.gradle b/android/build.gradle
index 305d3b3..3a5accb 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,6 +1,7 @@
buildscript {
repositories {
- jcenter()
+ google()
+ mavenCentral()
}
dependencies {
@@ -32,7 +33,15 @@ repositories {
dependencies {
implementation 'com.facebook.react:react-native:+'
implementation 'androidx.cardview:cardview:1.0.0'
- implementation 'com.github.bumptech.glide:glide:4.12.0'
- annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+
+ // Glide v4.16.0
+ implementation 'com.github.bumptech.glide:glide:4.16.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
+
+ // AVIF support
+ implementation 'com.github.bumptech.glide:avif-integration:4.16.0'
+
+ // SVG support
+ api 'com.caverock:androidsvg-aar:1.4'
}
\ No newline at end of file
diff --git a/android/src/main/java/com/reactlibrary/BlastedImageModule.java b/android/src/main/java/com/reactlibrary/BlastedImageModule.java
index 4192963..5c7841e 100644
--- a/android/src/main/java/com/reactlibrary/BlastedImageModule.java
+++ b/android/src/main/java/com/reactlibrary/BlastedImageModule.java
@@ -64,7 +64,7 @@ public BlastedImageModule(ReactApplicationContext reactContext) {
if (!isGlideInitialized) {
Glide.init(reactContext, new GlideBuilder()
.setDiskCache(new InternalCacheDiskCacheFactory(reactContext, 1024 * 1024 * 1024)) //1gb disk cache
- .setMemoryCache(new LruResourceCache(100 * 1024 * 1024)) // 100mb memory cache
+ .setMemoryCache(new LruResourceCache(256 * 1024 * 1024)) // 256mb memory cache
);
isGlideInitialized = true;
}
@@ -129,6 +129,7 @@ public Object prepareGlideUrl(String imageUrl, boolean hybridAssets, String clou
public void loadImage(String imageUrl, boolean skipMemoryCache, boolean hybridAssets, String cloudUrl, Promise promise) {
try {
+ // See BlastedImageModule.m for details regarding NativeEventEmitters (BlastedEventLog etc.)
Object glideUrl = prepareGlideUrl(imageUrl, hybridAssets, cloudUrl, true);
// Is skip skipMemoryCache set for image and should we store it only to disk?
diff --git a/android/src/main/java/com/reactlibrary/BlastedViewManager.java b/android/src/main/java/com/reactlibrary/BlastedViewManager.java
index 5cad740..1dfa00b 100644
--- a/android/src/main/java/com/reactlibrary/BlastedViewManager.java
+++ b/android/src/main/java/com/reactlibrary/BlastedViewManager.java
@@ -7,6 +7,8 @@
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
+import androidx.annotation.Nullable;
+
import android.widget.ImageView;
import android.view.View;
import android.view.ViewOutlineProvider;
@@ -16,6 +18,10 @@
import android.graphics.drawable.Drawable;
import android.graphics.Rect;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+
import android.util.Log;
@@ -117,5 +123,22 @@ public void setHeight(ImageView view, int height) {
}
}
+ @ReactProp(name = "tintColor")
+ public void setTintColor(ImageView view, @Nullable String color) {
+ if (color != null && !color.isEmpty()) {
+ try {
+ if (!color.startsWith("#") && color.length() == 6 && color.matches("[0-9A-Fa-f]+")) {
+ color = "#" + color;
+ }
+ int parsedColor = Color.parseColor(color);
+ view.setColorFilter(new PorterDuffColorFilter(parsedColor, PorterDuff.Mode.SRC_IN));
+ } catch (IllegalArgumentException e) {
+ Log.e("BlastedViewManager", "Invalid color format: " + color);
+ }
+ } else {
+ view.clearColorFilter();
+ }
+ }
+
// more properties... :)
}
diff --git a/android/src/main/java/com/reactlibrary/SvgDecoder.java b/android/src/main/java/com/reactlibrary/SvgDecoder.java
new file mode 100644
index 0000000..6f444f8
--- /dev/null
+++ b/android/src/main/java/com/reactlibrary/SvgDecoder.java
@@ -0,0 +1,29 @@
+package com.xerdnu.blastedimage;
+
+import androidx.annotation.NonNull;
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.ResourceDecoder;
+import com.bumptech.glide.load.engine.Resource;
+import com.bumptech.glide.load.resource.SimpleResource;
+import com.caverock.androidsvg.SVG;
+import com.caverock.androidsvg.SVGParseException;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class SvgDecoder implements ResourceDecoder {
+ @Override
+ public boolean handles(@NonNull InputStream source, @NonNull Options options) {
+ return true; // Assume all InputStreams are SVG
+ }
+
+ @Override
+ public Resource