react-native-nitro-web-image 0.5.0-beta.5
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.
- package/NitroWebImage.podspec +33 -0
- package/android/CMakeLists.txt +31 -0
- package/android/build.gradle +145 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/web/image/AsyncImagePriority+toCoroutineContext.kt +15 -0
- package/android/src/main/java/com/margelo/nitro/web/image/HybridWebImageFactory.kt +32 -0
- package/android/src/main/java/com/margelo/nitro/web/image/HybridWebImageLoader.kt +32 -0
- package/android/src/main/java/com/margelo/nitro/web/image/ImageLoader+loadImageAsync.kt +37 -0
- package/android/src/main/java/com/margelo/nitro/web/image/ImageRequestBuilder+applyOptions.kt +58 -0
- package/android/src/main/java/com/margelo/nitro/web/image/NitroWebImagePackage.java +44 -0
- package/ios/AsyncImageLoadOptions+toSDWebImageOptions.swift +66 -0
- package/ios/Bridge.h +8 -0
- package/ios/HybridWebImageFactory.swift +32 -0
- package/ios/HybridWebImageLoader.swift +54 -0
- package/ios/SDWebImageManager+loadImage.swift +30 -0
- package/lib/commonjs/index.js +9 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/specs/WebImageFactory.nitro.js +6 -0
- package/lib/commonjs/specs/WebImageFactory.nitro.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/specs/WebImageFactory.nitro.js +4 -0
- package/lib/module/specs/WebImageFactory.nitro.js.map +1 -0
- package/lib/tsconfig.build.tsbuildinfo +1 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/specs/WebImageFactory.nitro.d.ts +63 -0
- package/lib/typescript/specs/WebImageFactory.nitro.d.ts.map +1 -0
- package/nitro.json +18 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/NitroWebImage+autolinking.cmake +78 -0
- package/nitrogen/generated/android/NitroWebImage+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroWebImageOnLoad.cpp +46 -0
- package/nitrogen/generated/android/NitroWebImageOnLoad.hpp +25 -0
- package/nitrogen/generated/android/c++/JAsyncImageLoadOptions.hpp +88 -0
- package/nitrogen/generated/android/c++/JAsyncImagePriority.hpp +62 -0
- package/nitrogen/generated/android/c++/JHybridWebImageFactorySpec.cpp +82 -0
- package/nitrogen/generated/android/c++/JHybridWebImageFactorySpec.hpp +64 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/web/image/AsyncImageLoadOptions.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/web/image/AsyncImagePriority.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/web/image/HybridWebImageFactorySpec.kt +58 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/web/image/NitroWebImageOnLoad.kt +35 -0
- package/nitrogen/generated/ios/NitroWebImage+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroWebImage-Swift-Cxx-Bridge.cpp +65 -0
- package/nitrogen/generated/ios/NitroWebImage-Swift-Cxx-Bridge.hpp +197 -0
- package/nitrogen/generated/ios/NitroWebImage-Swift-Cxx-Umbrella.hpp +62 -0
- package/nitrogen/generated/ios/NitroWebImageAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroWebImageAutolinking.swift +25 -0
- package/nitrogen/generated/ios/c++/HybridWebImageFactorySpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridWebImageFactorySpecSwift.hpp +95 -0
- package/nitrogen/generated/ios/swift/AsyncImageLoadOptions.swift +237 -0
- package/nitrogen/generated/ios/swift/AsyncImagePriority.swift +44 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_margelo__nitro__image__HybridImageSpec_.swift +51 -0
- package/nitrogen/generated/ios/swift/HybridWebImageFactorySpec.swift +51 -0
- package/nitrogen/generated/ios/swift/HybridWebImageFactorySpec_cxx.swift +161 -0
- package/nitrogen/generated/shared/c++/AsyncImageLoadOptions.hpp +104 -0
- package/nitrogen/generated/shared/c++/AsyncImagePriority.hpp +82 -0
- package/nitrogen/generated/shared/c++/HybridWebImageFactorySpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridWebImageFactorySpec.hpp +74 -0
- package/package.json +113 -0
- package/react-native.config.js +16 -0
- package/src/index.ts +5 -0
- package/src/specs/WebImageFactory.nitro.ts +76 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "NitroWebImage"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported, :visionos => 1.0 }
|
|
14
|
+
s.source = { :git => "https://github.com/mrousavy/nitro.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = [
|
|
17
|
+
# Implementation (Swift)
|
|
18
|
+
"ios/**/*.{swift}",
|
|
19
|
+
# Autolinking/Registration (Objective-C++)
|
|
20
|
+
"ios/**/*.{m,mm}",
|
|
21
|
+
# Implementation (C++ objects)
|
|
22
|
+
"cpp/**/*.{hpp,cpp}",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
load 'nitrogen/generated/ios/NitroWebImage+autolinking.rb'
|
|
26
|
+
add_nitrogen_files(s)
|
|
27
|
+
|
|
28
|
+
s.dependency 'React-jsi'
|
|
29
|
+
s.dependency 'React-callinvoker'
|
|
30
|
+
s.dependency 'SDWebImage'
|
|
31
|
+
s.dependency 'NitroImage'
|
|
32
|
+
install_modules_dependencies(s)
|
|
33
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
project(NitroWebImage)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set (PACKAGE_NAME NitroWebImage)
|
|
5
|
+
set (CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
+
set (CMAKE_CXX_STANDARD 20)
|
|
7
|
+
|
|
8
|
+
# Define C++ library and add all sources
|
|
9
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
10
|
+
src/main/cpp/cpp-adapter.cpp
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
# Add Nitrogen specs :)
|
|
14
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroWebImage+autolinking.cmake)
|
|
15
|
+
|
|
16
|
+
# Set up local includes
|
|
17
|
+
include_directories(
|
|
18
|
+
"src/main/cpp"
|
|
19
|
+
"../cpp"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
find_library(LOG_LIB log)
|
|
23
|
+
find_package(react-native-nitro-image REQUIRED) # <-- for the HybridImage type
|
|
24
|
+
|
|
25
|
+
# Link all libraries together
|
|
26
|
+
target_link_libraries(
|
|
27
|
+
${PACKAGE_NAME}
|
|
28
|
+
${LOG_LIB}
|
|
29
|
+
android # <-- Android core
|
|
30
|
+
react-native-nitro-image::NitroImage # <-- NitroImage
|
|
31
|
+
)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.10.1"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def reactNativeArchitectures() {
|
|
13
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
14
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
23
|
+
apply from: '../nitrogen/generated/android/NitroWebImage+autolinking.gradle'
|
|
24
|
+
|
|
25
|
+
if (isNewArchitectureEnabled()) {
|
|
26
|
+
apply plugin: "com.facebook.react"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
def getExtOrDefault(name) {
|
|
30
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["NitroImage_" + name]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def getExtOrIntegerDefault(name) {
|
|
34
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["NitroImage_" + name]).toInteger()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
android {
|
|
38
|
+
namespace "com.margelo.nitro.web.image"
|
|
39
|
+
|
|
40
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
41
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
42
|
+
|
|
43
|
+
defaultConfig {
|
|
44
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
45
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
46
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
47
|
+
|
|
48
|
+
externalNativeBuild {
|
|
49
|
+
cmake {
|
|
50
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
51
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON"
|
|
52
|
+
abiFilters (*reactNativeArchitectures())
|
|
53
|
+
|
|
54
|
+
buildTypes {
|
|
55
|
+
debug {
|
|
56
|
+
cppFlags "-O1 -g"
|
|
57
|
+
}
|
|
58
|
+
release {
|
|
59
|
+
cppFlags "-O2"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
externalNativeBuild {
|
|
67
|
+
cmake {
|
|
68
|
+
path "CMakeLists.txt"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
packagingOptions {
|
|
73
|
+
excludes = [
|
|
74
|
+
"META-INF",
|
|
75
|
+
"META-INF/**",
|
|
76
|
+
"**/libc++_shared.so",
|
|
77
|
+
"**/libfbjni.so",
|
|
78
|
+
"**/libjsi.so",
|
|
79
|
+
"**/libfolly_json.so",
|
|
80
|
+
"**/libfolly_runtime.so",
|
|
81
|
+
"**/libglog.so",
|
|
82
|
+
"**/libhermes.so",
|
|
83
|
+
"**/libhermes-executor-debug.so",
|
|
84
|
+
"**/libhermes_executor.so",
|
|
85
|
+
"**/libreactnative.so",
|
|
86
|
+
"**/libreactnativejni.so",
|
|
87
|
+
"**/libturbomodulejsijni.so",
|
|
88
|
+
"**/libreact_nativemodule_core.so",
|
|
89
|
+
"**/libjscexecutor.so"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
buildFeatures {
|
|
94
|
+
buildConfig true
|
|
95
|
+
prefab true
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
buildTypes {
|
|
99
|
+
release {
|
|
100
|
+
minifyEnabled false
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
lintOptions {
|
|
105
|
+
disable "GradleCompatible"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
compileOptions {
|
|
109
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
110
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
sourceSets {
|
|
114
|
+
main {
|
|
115
|
+
if (isNewArchitectureEnabled()) {
|
|
116
|
+
java.srcDirs += [
|
|
117
|
+
// React Codegen files
|
|
118
|
+
"${project.buildDir}/generated/source/codegen/java"
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
repositories {
|
|
126
|
+
mavenCentral()
|
|
127
|
+
google()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
dependencies {
|
|
132
|
+
// For < 0.71, this will be from the local maven repo
|
|
133
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
134
|
+
//noinspection GradleDynamicVersion
|
|
135
|
+
implementation "com.facebook.react:react-native:+"
|
|
136
|
+
|
|
137
|
+
// Add a dependency on NitroModules
|
|
138
|
+
implementation project(":react-native-nitro-modules")
|
|
139
|
+
// Add a dependency on NitroImage
|
|
140
|
+
implementation project(":react-native-nitro-image")
|
|
141
|
+
// Coil
|
|
142
|
+
implementation("io.coil-kt.coil3:coil:3.3.0")
|
|
143
|
+
implementation("io.coil-kt.coil3:coil-network-okhttp:3.3.0")
|
|
144
|
+
}
|
|
145
|
+
|
package/android/src/main/java/com/margelo/nitro/web/image/AsyncImagePriority+toCoroutineContext.kt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.margelo.nitro.web.image
|
|
2
|
+
|
|
3
|
+
import kotlinx.coroutines.Dispatchers
|
|
4
|
+
import kotlinx.coroutines.currentCoroutineContext
|
|
5
|
+
import kotlin.coroutines.CoroutineContext
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
fun AsyncImagePriority.toCoroutineContext(): CoroutineContext? {
|
|
9
|
+
// TODO: Does this look about right?
|
|
10
|
+
return when (this) {
|
|
11
|
+
AsyncImagePriority.LOW -> Dispatchers.IO.limitedParallelism(2)
|
|
12
|
+
AsyncImagePriority.DEFAULT -> null
|
|
13
|
+
AsyncImagePriority.HIGH -> Dispatchers.IO
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.margelo.nitro.web.image
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.Keep
|
|
4
|
+
import coil3.ImageLoader
|
|
5
|
+
import com.facebook.common.internal.DoNotStrip
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.margelo.nitro.NitroModules
|
|
8
|
+
import com.margelo.nitro.core.Promise
|
|
9
|
+
import com.margelo.nitro.image.HybridImageLoaderSpec
|
|
10
|
+
import com.margelo.nitro.image.HybridImageSpec
|
|
11
|
+
|
|
12
|
+
@DoNotStrip
|
|
13
|
+
@Keep
|
|
14
|
+
class HybridWebImageFactory: HybridWebImageFactorySpec() {
|
|
15
|
+
private val context: ReactApplicationContext
|
|
16
|
+
get() = NitroModules.applicationContext ?: throw Error("No context - NitroModules.applicationContext was null!")
|
|
17
|
+
private val imageLoader = ImageLoader(context)
|
|
18
|
+
|
|
19
|
+
override fun createWebImageLoader(
|
|
20
|
+
url: String,
|
|
21
|
+
options: AsyncImageLoadOptions?
|
|
22
|
+
): HybridImageLoaderSpec {
|
|
23
|
+
return HybridWebImageLoader(imageLoader, url, options, context)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override fun loadFromURLAsync(
|
|
27
|
+
url: String,
|
|
28
|
+
options: AsyncImageLoadOptions?
|
|
29
|
+
): Promise<HybridImageSpec> {
|
|
30
|
+
return imageLoader.loadImageAsync(url, options, context)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.margelo.nitro.web.image
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.widget.ImageView
|
|
5
|
+
import coil3.ImageLoader
|
|
6
|
+
import coil3.load
|
|
7
|
+
import com.margelo.nitro.core.Promise
|
|
8
|
+
import com.margelo.nitro.image.HybridImageSpec
|
|
9
|
+
import com.margelo.nitro.image.HybridImageLoaderSpec
|
|
10
|
+
import com.margelo.nitro.image.HybridNitroImageViewSpec
|
|
11
|
+
|
|
12
|
+
class HybridWebImageLoader(private val imageLoader: ImageLoader,
|
|
13
|
+
private val url: String,
|
|
14
|
+
private val options: AsyncImageLoadOptions?,
|
|
15
|
+
private val context: Context) : HybridImageLoaderSpec() {
|
|
16
|
+
override fun loadImage(): Promise<HybridImageSpec> {
|
|
17
|
+
return imageLoader.loadImageAsync(url, options, context)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override fun requestImage(forView: HybridNitroImageViewSpec) {
|
|
21
|
+
val imageView = forView.view as? ImageView ?: return
|
|
22
|
+
|
|
23
|
+
imageView.load(url, imageLoader) {
|
|
24
|
+
this.applyOptions(options)
|
|
25
|
+
}
|
|
26
|
+
imageView.load(url)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
override fun dropImage(forView: HybridNitroImageViewSpec) {
|
|
30
|
+
// Coil automatically handles recycling here - I _think_.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package com.margelo.nitro.web.image
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import coil3.BitmapImage
|
|
5
|
+
import coil3.Image
|
|
6
|
+
import coil3.ImageLoader
|
|
7
|
+
import coil3.request.ImageRequest
|
|
8
|
+
import com.margelo.nitro.core.Promise
|
|
9
|
+
import com.margelo.nitro.image.HybridImage
|
|
10
|
+
import com.margelo.nitro.image.HybridImageSpec
|
|
11
|
+
|
|
12
|
+
suspend fun ImageLoader.loadCoilImageAsync(url: String,
|
|
13
|
+
options: AsyncImageLoadOptions?,
|
|
14
|
+
context: Context): Image {
|
|
15
|
+
// 1. Create the Coil Request
|
|
16
|
+
val request = ImageRequest.Builder(context)
|
|
17
|
+
.data(url)
|
|
18
|
+
.applyOptions(options)
|
|
19
|
+
.build()
|
|
20
|
+
// 2. Execute it (async)
|
|
21
|
+
val result = this.execute(request)
|
|
22
|
+
val image = result.image ?: throw Error("Failed to load Image!")
|
|
23
|
+
return image
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
fun ImageLoader.loadImageAsync(url: String,
|
|
27
|
+
options: AsyncImageLoadOptions?,
|
|
28
|
+
context: Context
|
|
29
|
+
): Promise<HybridImageSpec> {
|
|
30
|
+
return Promise.async {
|
|
31
|
+
// 1. Load the coil image
|
|
32
|
+
val image = loadCoilImageAsync(url, options, context)
|
|
33
|
+
// 3. Downcast to a Bitmap - if that fails, it might be an Animated Image...
|
|
34
|
+
val bitmap = image as? BitmapImage ?: throw Error("Requested Image is not a Bitmap!")
|
|
35
|
+
return@async HybridImage(bitmap.bitmap)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package com.margelo.nitro.web.image
|
|
2
|
+
|
|
3
|
+
import coil3.annotation.ExperimentalCoilApi
|
|
4
|
+
import coil3.decode.BlackholeDecoder
|
|
5
|
+
import coil3.request.CachePolicy
|
|
6
|
+
import coil3.request.ImageRequest
|
|
7
|
+
import coil3.size.Precision
|
|
8
|
+
|
|
9
|
+
@OptIn(ExperimentalCoilApi::class)
|
|
10
|
+
fun ImageRequest.Builder.applyOptions(options: AsyncImageLoadOptions?): ImageRequest.Builder {
|
|
11
|
+
if (options == null) return this
|
|
12
|
+
var result = this
|
|
13
|
+
|
|
14
|
+
if (options.priority != null) {
|
|
15
|
+
options.priority.toCoroutineContext()?.let { context ->
|
|
16
|
+
result = result.coroutineContext(context)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (options.forceRefresh == true) {
|
|
21
|
+
// don't allow reading from cache, only writing.
|
|
22
|
+
result = result.diskCachePolicy(CachePolicy.WRITE_ONLY)
|
|
23
|
+
result = result.memoryCachePolicy(CachePolicy.WRITE_ONLY)
|
|
24
|
+
result = result.networkCachePolicy(CachePolicy.WRITE_ONLY)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (options.continueInBackground == true) {
|
|
28
|
+
// TODO: Implement .continueInBackground
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (options.allowInvalidSSLCertificates == true) {
|
|
32
|
+
// TODO: Implement .allowInvalidSSLCertificates
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (options.scaleDownLargeImages == true) {
|
|
36
|
+
// Limit to 4096x4096 (~60 MB)
|
|
37
|
+
result = result.size(4096, 4096)
|
|
38
|
+
result = result.precision(Precision.INEXACT)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (options.queryMemoryDataSync == true) {
|
|
42
|
+
// TODO: Implement .queryMemoryDataSync
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (options.queryDiskDataSync == true) {
|
|
46
|
+
// TODO: Implement .queryDiskDataSync
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (options.decodeImage == false) {
|
|
50
|
+
result = result.decoderFactory(BlackholeDecoder.Factory())
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (options.cacheKey != null) {
|
|
54
|
+
result = result.diskCacheKey(options.cacheKey)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return result
|
|
58
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
package com.margelo.nitro.web.image;
|
|
2
|
+
|
|
3
|
+
import android.util.Log;
|
|
4
|
+
|
|
5
|
+
import androidx.annotation.NonNull;
|
|
6
|
+
import androidx.annotation.Nullable;
|
|
7
|
+
|
|
8
|
+
import com.facebook.react.bridge.NativeModule;
|
|
9
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
10
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
11
|
+
import com.facebook.react.TurboReactPackage;
|
|
12
|
+
import com.facebook.react.uimanager.ViewManager;
|
|
13
|
+
import com.margelo.nitro.core.HybridObject;
|
|
14
|
+
|
|
15
|
+
import java.util.ArrayList;
|
|
16
|
+
import java.util.HashMap;
|
|
17
|
+
import java.util.List;
|
|
18
|
+
import java.util.function.Supplier;
|
|
19
|
+
|
|
20
|
+
public class NitroWebImagePackage extends TurboReactPackage {
|
|
21
|
+
@Nullable
|
|
22
|
+
@Override
|
|
23
|
+
public NativeModule getModule(String name, ReactApplicationContext reactContext) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Override
|
|
28
|
+
public ReactModuleInfoProvider getReactModuleInfoProvider() {
|
|
29
|
+
return () -> {
|
|
30
|
+
return new HashMap<>();
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@Override
|
|
36
|
+
public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
|
|
37
|
+
List<ViewManager> viewManagers = new ArrayList<>();
|
|
38
|
+
return viewManagers;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static {
|
|
42
|
+
NitroWebImageOnLoad.initializeNative();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AsyncImageLoadOptions+toSDWebImageOptions.swift
|
|
3
|
+
// NitroWebImage
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 30.06.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import SDWebImage
|
|
10
|
+
|
|
11
|
+
extension AsyncImageLoadOptions {
|
|
12
|
+
func toSDWebImageOptions() -> SDWebImageOptions {
|
|
13
|
+
var options: SDWebImageOptions = []
|
|
14
|
+
|
|
15
|
+
switch priority {
|
|
16
|
+
case .default, .none:
|
|
17
|
+
break
|
|
18
|
+
case .low:
|
|
19
|
+
options.insert(.lowPriority)
|
|
20
|
+
case .high:
|
|
21
|
+
options.insert(.highPriority)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if forceRefresh == true {
|
|
25
|
+
options.insert(.refreshCached)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if continueInBackground == true {
|
|
29
|
+
options.insert(.continueInBackground)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if allowInvalidSSLCertificates == true {
|
|
33
|
+
options.insert(.allowInvalidSSLCertificates)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if scaleDownLargeImages == true {
|
|
37
|
+
options.insert(.scaleDownLargeImages)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if queryMemoryDataSync == true {
|
|
41
|
+
options.insert(.queryMemoryDataSync)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if queryDiskDataSync == true {
|
|
45
|
+
options.insert(.queryDiskDataSync)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if decodeImage == false {
|
|
49
|
+
options.insert(.avoidDecodeImage)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return options
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func toSDWebImageContext() -> [SDWebImageContextOption: Any] {
|
|
56
|
+
var context: [SDWebImageContextOption: Any] = [:]
|
|
57
|
+
|
|
58
|
+
if let cacheKey {
|
|
59
|
+
context[.cacheKeyFilter] = SDWebImageCacheKeyFilter { _ in
|
|
60
|
+
return cacheKey
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return context
|
|
65
|
+
}
|
|
66
|
+
}
|
package/ios/Bridge.h
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HybridWebImageFactory.swift
|
|
3
|
+
// react-native-nitro-web-image
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 10.06.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import NitroModules
|
|
10
|
+
import SDWebImage
|
|
11
|
+
import NitroImage
|
|
12
|
+
|
|
13
|
+
class HybridWebImageFactory: HybridWebImageFactorySpec {
|
|
14
|
+
func loadFromURLAsync(url: String, options: AsyncImageLoadOptions?) throws -> Promise<any HybridImageSpec> {
|
|
15
|
+
throw RuntimeError.error(withMessage: "Not yet implemented!")
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private let queue = DispatchQueue(label: "image-loader",
|
|
19
|
+
qos: .default,
|
|
20
|
+
attributes: .concurrent)
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Load Image from URL
|
|
24
|
+
*/
|
|
25
|
+
func createWebImageLoader(url urlString: String, options: AsyncImageLoadOptions?) throws -> any HybridImageLoaderSpec {
|
|
26
|
+
guard let url = URL(string: urlString) else {
|
|
27
|
+
throw RuntimeError.error(withMessage: "URL string \"\(urlString)\" is not a valid URL!")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return HybridWebImageLoader(url: url, options: options)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HybridWebImageLoader.swift
|
|
3
|
+
// NitroWebImage
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 28.07.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import NitroModules
|
|
9
|
+
import SDWebImage
|
|
10
|
+
import NitroImage
|
|
11
|
+
|
|
12
|
+
fileprivate class HybridImage: HybridImageSpec, NativeImage {
|
|
13
|
+
let uiImage: UIImage
|
|
14
|
+
init(uiImage: UIImage) {
|
|
15
|
+
self.uiImage = uiImage
|
|
16
|
+
super.init()
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class HybridWebImageLoader: HybridImageLoaderSpec {
|
|
21
|
+
private let url: URL
|
|
22
|
+
private let options: AsyncImageLoadOptions?
|
|
23
|
+
|
|
24
|
+
init(url: URL, options: AsyncImageLoadOptions?) {
|
|
25
|
+
self.url = url
|
|
26
|
+
self.options = options
|
|
27
|
+
super.init()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func loadImage() throws -> Promise<(any HybridImageSpec)> {
|
|
31
|
+
return Promise.async {
|
|
32
|
+
let webImageOptions = self.options?.toSDWebImageOptions() ?? []
|
|
33
|
+
let webImageContext = self.options?.toSDWebImageContext() ?? [:]
|
|
34
|
+
let uiImage = try await SDWebImageManager.shared.loadImage(with: self.url,
|
|
35
|
+
options: webImageOptions,
|
|
36
|
+
context: webImageContext)
|
|
37
|
+
return HybridImage(uiImage: uiImage)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
func requestImage(forView view: (any HybridNitroImageViewSpec)) throws {
|
|
42
|
+
guard let view = view as? NativeImageView else { throw RuntimeError.error(withMessage: "Invalid view type!") }
|
|
43
|
+
|
|
44
|
+
let webImageOptions = options?.toSDWebImageOptions() ?? []
|
|
45
|
+
view.imageView.sd_setImage(with: url,
|
|
46
|
+
placeholderImage: nil,
|
|
47
|
+
options: webImageOptions,
|
|
48
|
+
context: nil)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
func dropImage(forView view: (any HybridNitroImageViewSpec)) throws {
|
|
52
|
+
// TODO: Do we need to reset the image here or not?
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SDWebImageManager+loadImage.swift
|
|
3
|
+
// NitroWebImage
|
|
4
|
+
//
|
|
5
|
+
// Created by Marc Rousavy on 30.06.25.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import SDWebImage
|
|
10
|
+
import NitroModules
|
|
11
|
+
|
|
12
|
+
extension SDWebImageManager {
|
|
13
|
+
func loadImage(with url: URL, options: SDWebImageOptions) async throws -> UIImage {
|
|
14
|
+
return try await withUnsafeThrowingContinuation { continuation in
|
|
15
|
+
self.loadImage(with: url, options: options) { current, total, url in
|
|
16
|
+
print("\(url): Loaded \(current)/\(total) bytes")
|
|
17
|
+
} completed: { image, data, error, cacheType, finished, url in
|
|
18
|
+
if let image {
|
|
19
|
+
continuation.resume(returning: image)
|
|
20
|
+
} else {
|
|
21
|
+
if let error {
|
|
22
|
+
continuation.resume(throwing: error)
|
|
23
|
+
} else {
|
|
24
|
+
continuation.resume(throwing: RuntimeError.error(withMessage: "No Image or error was returned!"))
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.WebImages = void 0;
|
|
7
|
+
var _reactNativeNitroModules = require("react-native-nitro-modules");
|
|
8
|
+
const WebImages = exports.WebImages = _reactNativeNitroModules.NitroModules.createHybridObject("WebImageFactory");
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNativeNitroModules","require","WebImages","exports","NitroModules","createHybridObject"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;AAAA,IAAAA,wBAAA,GAAAC,OAAA;AAGO,MAAMC,SAAS,GAAAC,OAAA,CAAAD,SAAA,GAClBE,qCAAY,CAACC,kBAAkB,CAAkB,iBAAiB,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../../src","sources":["specs/WebImageFactory.nitro.ts"],"mappings":"","ignoreList":[]}
|