@onekeyfe/react-native-image 3.0.117 → 3.0.118
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/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImage.kt +107 -13
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageReusableView.kt +2 -0
- package/ios/OneKeyAvatarImageLoader.swift +3 -1
- package/ios/OneKeyImage.swift +186 -17
- package/ios/OneKeyImageReusableView.swift +2 -0
- package/lib/module/index.js +4 -2
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.cpp +9 -0
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.hpp +2 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.cpp +5 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt +6 -0
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.hpp +7 -0
- package/lib/nitrogen/generated/ios/c++/views/HybridOneKeyImageComponent.mm +6 -0
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageSpec.swift +1 -0
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageSpec_cxx.swift +24 -0
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.cpp +2 -0
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.hpp +2 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.cpp +2 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.hpp +3 -0
- package/lib/nitrogen/generated/shared/json/OneKeyImageConfig.json +1 -0
- package/lib/typescript/src/OneKeyImage.nitro.d.ts +2 -0
- package/lib/typescript/src/index.d.ts +1 -1
- package/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.cpp +9 -0
- package/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.hpp +2 -0
- package/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.cpp +5 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt +6 -0
- package/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.hpp +7 -0
- package/nitrogen/generated/ios/c++/views/HybridOneKeyImageComponent.mm +6 -0
- package/nitrogen/generated/ios/swift/HybridOneKeyImageSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridOneKeyImageSpec_cxx.swift +24 -0
- package/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.cpp +2 -0
- package/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.hpp +2 -0
- package/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.cpp +2 -0
- package/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.hpp +3 -0
- package/nitrogen/generated/shared/json/OneKeyImageConfig.json +1 -0
- package/package.json +2 -2
- package/src/OneKeyImage.nitro.ts +2 -0
- package/src/index.tsx +3 -1
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
package com.margelo.nitro.onekeyimage
|
|
2
2
|
|
|
3
|
+
import android.animation.ValueAnimator
|
|
3
4
|
import android.app.Activity
|
|
4
5
|
import android.content.Context
|
|
5
6
|
import android.content.ContextWrapper
|
|
7
|
+
import android.content.res.Configuration
|
|
6
8
|
import android.graphics.Canvas
|
|
7
9
|
import android.graphics.Color
|
|
8
10
|
import android.graphics.Paint
|
|
9
11
|
import android.graphics.drawable.Animatable
|
|
10
12
|
import android.graphics.drawable.Drawable
|
|
13
|
+
import android.os.Build
|
|
14
|
+
import android.os.SystemClock
|
|
15
|
+
import android.provider.Settings
|
|
11
16
|
import android.view.View
|
|
17
|
+
import android.view.animation.DecelerateInterpolator
|
|
12
18
|
import android.widget.ImageView
|
|
13
19
|
import com.bumptech.glide.Glide
|
|
14
20
|
import com.bumptech.glide.load.DataSource
|
|
@@ -88,8 +94,16 @@ private class OneKeyImageHostView(context: ThemedReactContext) : ImageView(conte
|
|
|
88
94
|
syncPlayback()
|
|
89
95
|
}
|
|
90
96
|
|
|
91
|
-
fun updateSkeletonStyle() {
|
|
92
|
-
|
|
97
|
+
fun updateSkeletonStyle(baseColor: Int) {
|
|
98
|
+
val average = (Color.red(baseColor) + Color.green(baseColor) + Color.blue(baseColor)) / 3
|
|
99
|
+
val delta = if (average < 128) 18 else -12
|
|
100
|
+
val highlightColor = Color.argb(
|
|
101
|
+
Color.alpha(baseColor),
|
|
102
|
+
(Color.red(baseColor) + delta).coerceIn(0, 255),
|
|
103
|
+
(Color.green(baseColor) + delta).coerceIn(0, 255),
|
|
104
|
+
(Color.blue(baseColor) + delta).coerceIn(0, 255),
|
|
105
|
+
)
|
|
106
|
+
skeleton.updateStyle(intArrayOf(baseColor, highlightColor), 3.0)
|
|
93
107
|
skeleton.updateBounds(width, height)
|
|
94
108
|
}
|
|
95
109
|
|
|
@@ -137,6 +151,10 @@ internal fun oneKeyImageRequestSignature(
|
|
|
137
151
|
class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
138
152
|
HybridOneKeyImageSpec(), RecyclableView {
|
|
139
153
|
private enum class DisplayState { LOADING, IMAGE, ERROR, FALLBACK }
|
|
154
|
+
private companion object {
|
|
155
|
+
const val FADE_DELAY_THRESHOLD_MS = 100L
|
|
156
|
+
const val FADE_DURATION_MS = 140L
|
|
157
|
+
}
|
|
140
158
|
|
|
141
159
|
private val hostView = OneKeyImageHostView(context)
|
|
142
160
|
// The Activity outlives ScreenStack Fragments but still provides bounded
|
|
@@ -156,6 +174,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
156
174
|
private var displayRunnable: Runnable? = null
|
|
157
175
|
private var pendingDisplayGeneration: Long? = null
|
|
158
176
|
private var fallbackRunnable: Runnable? = null
|
|
177
|
+
private var requestStartedAtMs: Long? = null
|
|
159
178
|
|
|
160
179
|
/**
|
|
161
180
|
* Native reusable containers own their request cleanup explicitly, so their
|
|
@@ -236,6 +255,11 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
236
255
|
field = value
|
|
237
256
|
if (!suppressPropEffects) applyVariant()
|
|
238
257
|
}
|
|
258
|
+
override var placeholderColor: String? = null
|
|
259
|
+
set(value) {
|
|
260
|
+
field = value
|
|
261
|
+
if (!suppressPropEffects) applyVariant()
|
|
262
|
+
}
|
|
239
263
|
override var onLoadStart: (() -> Unit)? = null
|
|
240
264
|
override var onLoad: ((width: Double, height: Double, cacheType: OneKeyImageCacheType) -> Unit)? = null
|
|
241
265
|
override var onDisplay: (() -> Unit)? = null
|
|
@@ -244,7 +268,6 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
244
268
|
|
|
245
269
|
init {
|
|
246
270
|
OneKeyImageGlideRegistry.ensureRegistered(context)
|
|
247
|
-
hostView.updateSkeletonStyle()
|
|
248
271
|
hostView.onReadyForRequest = { scheduleLoad() }
|
|
249
272
|
hostView.onAttachmentChanged = { attached ->
|
|
250
273
|
if (attached) {
|
|
@@ -317,6 +340,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
317
340
|
resizeWidth = null
|
|
318
341
|
overscan = 1.1
|
|
319
342
|
loadingStrategy = OneKeyImageLoadingStrategy.STATIC
|
|
343
|
+
placeholderColor = null
|
|
320
344
|
onLoadStart = null
|
|
321
345
|
onLoad = null
|
|
322
346
|
onDisplay = null
|
|
@@ -375,6 +399,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
375
399
|
|
|
376
400
|
cancelCurrent(invalidateGeneration = true)
|
|
377
401
|
val requestGeneration = generation
|
|
402
|
+
requestStartedAtMs = SystemClock.uptimeMillis()
|
|
378
403
|
onLoadStart?.invoke()
|
|
379
404
|
|
|
380
405
|
val customIdentity = OneKeyImageModel.headers(sourceHeadersJson).isNotEmpty()
|
|
@@ -430,6 +455,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
430
455
|
hostView.drawStateSymbol = false
|
|
431
456
|
hostView.setBackgroundColor(Color.TRANSPARENT)
|
|
432
457
|
hostView.setImageDrawable(resource)
|
|
458
|
+
applyLoadedImageTransition(resolvedCacheType)
|
|
433
459
|
applyAutoplay()
|
|
434
460
|
val loadCallback = onLoad
|
|
435
461
|
val loadEndCallback = onLoadEnd
|
|
@@ -563,6 +589,8 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
563
589
|
clearCurrentTarget()
|
|
564
590
|
requestActive = false
|
|
565
591
|
hostView.skeletonRequested = false
|
|
592
|
+
requestStartedAtMs = null
|
|
593
|
+
resetImageTransition()
|
|
566
594
|
if (invalidateGeneration) generation++
|
|
567
595
|
}
|
|
568
596
|
|
|
@@ -605,6 +633,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
605
633
|
private fun showLoading(requestIsActive: Boolean) {
|
|
606
634
|
displayState = DisplayState.LOADING
|
|
607
635
|
requestActive = requestIsActive
|
|
636
|
+
resetImageTransition()
|
|
608
637
|
hostView.setImageDrawable(null)
|
|
609
638
|
hostView.drawStateSymbol = false
|
|
610
639
|
applyLoadingAppearance()
|
|
@@ -621,11 +650,15 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
621
650
|
private fun showTerminalState(state: DisplayState) {
|
|
622
651
|
displayState = state
|
|
623
652
|
requestActive = false
|
|
653
|
+
resetImageTransition()
|
|
624
654
|
hostView.setImageDrawable(null)
|
|
625
655
|
hostView.skeletonRequested = false
|
|
626
|
-
|
|
656
|
+
val hidesTerminalState = loadingStrategy == OneKeyImageLoadingStrategy.NONE
|
|
657
|
+
hostView.drawStateSymbol = !hidesTerminalState
|
|
627
658
|
hostView.stateSymbol = stateSymbol()
|
|
628
|
-
hostView.setBackgroundColor(
|
|
659
|
+
hostView.setBackgroundColor(
|
|
660
|
+
if (hidesTerminalState) Color.TRANSPARENT else resolvedPlaceholderColor(),
|
|
661
|
+
)
|
|
629
662
|
hostView.invalidate()
|
|
630
663
|
}
|
|
631
664
|
|
|
@@ -634,7 +667,11 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
634
667
|
DisplayState.IMAGE -> Unit
|
|
635
668
|
DisplayState.LOADING -> applyLoadingAppearance()
|
|
636
669
|
DisplayState.ERROR, DisplayState.FALLBACK -> {
|
|
637
|
-
|
|
670
|
+
val hidesTerminalState = loadingStrategy == OneKeyImageLoadingStrategy.NONE
|
|
671
|
+
hostView.setBackgroundColor(
|
|
672
|
+
if (hidesTerminalState) Color.TRANSPARENT else resolvedPlaceholderColor(),
|
|
673
|
+
)
|
|
674
|
+
hostView.drawStateSymbol = !hidesTerminalState
|
|
638
675
|
hostView.stateSymbol = stateSymbol()
|
|
639
676
|
hostView.invalidate()
|
|
640
677
|
}
|
|
@@ -643,11 +680,13 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
643
680
|
|
|
644
681
|
private fun applyLoadingAppearance() {
|
|
645
682
|
val strategy = loadingStrategy ?: OneKeyImageLoadingStrategy.STATIC
|
|
683
|
+
val placeholder = resolvedPlaceholderColor()
|
|
646
684
|
hostView.setBackgroundColor(
|
|
647
|
-
if (strategy == OneKeyImageLoadingStrategy.NONE) Color.TRANSPARENT else
|
|
685
|
+
if (strategy == OneKeyImageLoadingStrategy.NONE) Color.TRANSPARENT else placeholder,
|
|
648
686
|
)
|
|
687
|
+
hostView.updateSkeletonStyle(placeholder)
|
|
649
688
|
hostView.skeletonRequested =
|
|
650
|
-
requestActive && strategy == OneKeyImageLoadingStrategy.SKELETON
|
|
689
|
+
requestActive && strategy == OneKeyImageLoadingStrategy.SKELETON && animationsEnabled()
|
|
651
690
|
hostView.invalidate()
|
|
652
691
|
}
|
|
653
692
|
|
|
@@ -658,11 +697,66 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
658
697
|
OneKeyImageVariant.AVATAR -> "●"
|
|
659
698
|
}
|
|
660
699
|
|
|
661
|
-
private fun
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
700
|
+
private fun applyLoadedImageTransition(cacheType: OneKeyImageCacheType) {
|
|
701
|
+
resetImageTransition()
|
|
702
|
+
val startedAt = requestStartedAtMs ?: return
|
|
703
|
+
if (
|
|
704
|
+
cacheType == OneKeyImageCacheType.MEMORY ||
|
|
705
|
+
SystemClock.uptimeMillis() - startedAt < FADE_DELAY_THRESHOLD_MS ||
|
|
706
|
+
!animationsEnabled()
|
|
707
|
+
) {
|
|
708
|
+
return
|
|
709
|
+
}
|
|
710
|
+
hostView.alpha = 0f
|
|
711
|
+
hostView.animate()
|
|
712
|
+
.alpha(1f)
|
|
713
|
+
.setDuration(FADE_DURATION_MS)
|
|
714
|
+
.setInterpolator(DecelerateInterpolator())
|
|
715
|
+
.start()
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
private fun resetImageTransition() {
|
|
719
|
+
hostView.animate().cancel()
|
|
720
|
+
hostView.alpha = 1f
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
private fun animationsEnabled(): Boolean =
|
|
724
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
725
|
+
ValueAnimator.areAnimatorsEnabled()
|
|
726
|
+
} else {
|
|
727
|
+
Settings.Global.getFloat(
|
|
728
|
+
context.contentResolver,
|
|
729
|
+
Settings.Global.ANIMATOR_DURATION_SCALE,
|
|
730
|
+
1f,
|
|
731
|
+
) != 0f
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
private fun resolvedPlaceholderColor(): Int {
|
|
735
|
+
parseRgbaHex(placeholderColor)?.let { return it }
|
|
736
|
+
// OneKey patch: fall back to a dark-aware low-contrast fill instead of light-only RGB values.
|
|
737
|
+
// return when (variant ?: OneKeyImageVariant.GENERIC) {
|
|
738
|
+
// OneKeyImageVariant.GENERIC -> Color.rgb(232, 232, 232)
|
|
739
|
+
// OneKeyImageVariant.TOKEN -> Color.rgb(232, 237, 249)
|
|
740
|
+
// OneKeyImageVariant.NETWORK -> Color.rgb(229, 240, 245)
|
|
741
|
+
// OneKeyImageVariant.AVATAR -> Color.rgb(234, 234, 240)
|
|
742
|
+
// }
|
|
743
|
+
val nightMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
|
|
744
|
+
return if (nightMode == Configuration.UI_MODE_NIGHT_YES) {
|
|
745
|
+
Color.rgb(38, 38, 38)
|
|
746
|
+
} else {
|
|
747
|
+
Color.rgb(238, 238, 238)
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
private fun parseRgbaHex(value: String?): Int? {
|
|
752
|
+
val hex = value?.trim()?.removePrefix("#") ?: return null
|
|
753
|
+
if (hex.length != 6 && hex.length != 8) return null
|
|
754
|
+
val parsed = hex.toLongOrNull(16) ?: return null
|
|
755
|
+
val red = ((parsed shr (if (hex.length == 8) 24 else 16)) and 0xFF).toInt()
|
|
756
|
+
val green = ((parsed shr (if (hex.length == 8) 16 else 8)) and 0xFF).toInt()
|
|
757
|
+
val blue = ((parsed shr (if (hex.length == 8) 8 else 0)) and 0xFF).toInt()
|
|
758
|
+
val alpha = if (hex.length == 8) (parsed and 0xFF).toInt() else 0xFF
|
|
759
|
+
return Color.argb(alpha, red, green, blue)
|
|
666
760
|
}
|
|
667
761
|
|
|
668
762
|
private fun applyContentFit() {
|
|
@@ -28,6 +28,7 @@ class OneKeyImageReusableView(context: ThemedReactContext) : FrameLayout(context
|
|
|
28
28
|
optimizeTos: Boolean,
|
|
29
29
|
overscan: Double,
|
|
30
30
|
loadingStrategy: String,
|
|
31
|
+
placeholderColor: String,
|
|
31
32
|
onLoad: (() -> Unit)? = null,
|
|
32
33
|
onError: (() -> Unit)? = null,
|
|
33
34
|
) {
|
|
@@ -62,6 +63,7 @@ class OneKeyImageReusableView(context: ThemedReactContext) : FrameLayout(context
|
|
|
62
63
|
"none" -> OneKeyImageLoadingStrategy.NONE
|
|
63
64
|
else -> OneKeyImageLoadingStrategy.STATIC
|
|
64
65
|
}
|
|
66
|
+
image.placeholderColor = placeholderColor
|
|
65
67
|
image.sourceUri = sourceUri
|
|
66
68
|
image.afterUpdate()
|
|
67
69
|
}
|
|
@@ -11,7 +11,9 @@ final class OneKeyAvatarImageLoader: NSObject, SDImageLoader {
|
|
|
11
11
|
config.maxDiskAge = 30 * 24 * 60 * 60
|
|
12
12
|
config.maxDiskSize = 32 * 1024 * 1024
|
|
13
13
|
config.maxMemoryCost = 8 * 1024 * 1024
|
|
14
|
-
|
|
14
|
+
// OneKey patch: Keep several large-account wallets resident while the byte
|
|
15
|
+
// budget remains the hard memory bound.
|
|
16
|
+
config.maxMemoryCount = 512
|
|
15
17
|
return SDImageCache(namespace: "onekey-avatar-blockie-v1", diskCacheDirectory: nil, config: config)
|
|
16
18
|
}()
|
|
17
19
|
|
package/ios/OneKeyImage.swift
CHANGED
|
@@ -22,6 +22,7 @@ private final class OneKeyImageHostView: SDAnimatedImageView {
|
|
|
22
22
|
private final class OneKeyImageSkeletonView: UIView {
|
|
23
23
|
private lazy var renderer = OneKeySkeletonRenderer(hostLayer: layer)
|
|
24
24
|
private var requestedRunning = false
|
|
25
|
+
private var colors: [UIColor]?
|
|
25
26
|
|
|
26
27
|
override init(frame: CGRect) {
|
|
27
28
|
super.init(frame: frame)
|
|
@@ -36,7 +37,7 @@ private final class OneKeyImageSkeletonView: UIView {
|
|
|
36
37
|
|
|
37
38
|
override func layoutSubviews() {
|
|
38
39
|
super.layoutSubviews()
|
|
39
|
-
renderer.update(width: bounds.width, height: bounds.height)
|
|
40
|
+
renderer.update(width: bounds.width, height: bounds.height, colors: colors)
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
override func didMoveToWindow() {
|
|
@@ -50,9 +51,14 @@ private final class OneKeyImageSkeletonView: UIView {
|
|
|
50
51
|
syncRenderer()
|
|
51
52
|
}
|
|
52
53
|
|
|
54
|
+
func updateColors(_ colors: [UIColor]) {
|
|
55
|
+
self.colors = colors
|
|
56
|
+
renderer.update(width: bounds.width, height: bounds.height, colors: colors)
|
|
57
|
+
}
|
|
58
|
+
|
|
53
59
|
private func syncRenderer() {
|
|
54
60
|
if requestedRunning, window != nil, !bounds.isEmpty {
|
|
55
|
-
renderer.update(width: bounds.width, height: bounds.height)
|
|
61
|
+
renderer.update(width: bounds.width, height: bounds.height, colors: colors)
|
|
56
62
|
renderer.start()
|
|
57
63
|
} else {
|
|
58
64
|
renderer.stop()
|
|
@@ -66,7 +72,7 @@ private final class OneKeyImageSkeletonIndicator: NSObject, SDWebImageIndicator
|
|
|
66
72
|
var indicatorView: UIView { skeletonView }
|
|
67
73
|
|
|
68
74
|
func startAnimatingIndicator() {
|
|
69
|
-
skeletonView.setRunning(
|
|
75
|
+
skeletonView.setRunning(!UIAccessibility.isReduceMotionEnabled)
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
func stopAnimatingIndicator() {
|
|
@@ -76,10 +82,16 @@ private final class OneKeyImageSkeletonIndicator: NSObject, SDWebImageIndicator
|
|
|
76
82
|
func updateFrame(_ frame: CGRect) {
|
|
77
83
|
skeletonView.frame = frame
|
|
78
84
|
}
|
|
85
|
+
|
|
86
|
+
func updateColors(_ colors: [UIColor]) {
|
|
87
|
+
skeletonView.updateColors(colors)
|
|
88
|
+
}
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
82
92
|
private enum DisplayState { case loading, image, error, fallback }
|
|
93
|
+
private static let fadeDelayThreshold: CFTimeInterval = 0.1
|
|
94
|
+
private static let fadeDuration: TimeInterval = 0.14
|
|
83
95
|
|
|
84
96
|
private let hostView = OneKeyImageHostView()
|
|
85
97
|
private let skeletonIndicator = OneKeyImageSkeletonIndicator()
|
|
@@ -95,6 +107,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
95
107
|
private var requestActive = false
|
|
96
108
|
private var isResetting = false
|
|
97
109
|
private var displayState = DisplayState.loading
|
|
110
|
+
private var requestStartedAt: CFTimeInterval?
|
|
98
111
|
|
|
99
112
|
var view: UIView { hostView }
|
|
100
113
|
|
|
@@ -132,6 +145,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
132
145
|
}
|
|
133
146
|
}
|
|
134
147
|
var loadingStrategy: OneKeyImageLoadingStrategy? = .static { didSet { applyVariant() } }
|
|
148
|
+
var placeholderColor: String? { didSet { applyVariant() } }
|
|
135
149
|
var onLoadStart: (() -> Void)?
|
|
136
150
|
var onLoad: ((_ width: Double, _ height: Double, _ cacheType: OneKeyImageCacheType) -> Void)?
|
|
137
151
|
var onDisplay: (() -> Void)?
|
|
@@ -215,7 +229,9 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
215
229
|
self.cancelCurrentRequest(invalidateGeneration: true)
|
|
216
230
|
self.lastRequestSignature = nil
|
|
217
231
|
if let source = self.sourceUri, !source.isEmpty {
|
|
218
|
-
self.
|
|
232
|
+
if !self.showMemoryCachedImageIfAvailable(requestIsActive: false) {
|
|
233
|
+
self.showLoading(requestIsActive: false, letLibraryStartIndicator: false)
|
|
234
|
+
}
|
|
219
235
|
} else {
|
|
220
236
|
self.showFallback()
|
|
221
237
|
}
|
|
@@ -258,9 +274,11 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
258
274
|
|
|
259
275
|
cancelCurrentRequest(invalidateGeneration: true)
|
|
260
276
|
let generation = requestGeneration
|
|
261
|
-
|
|
277
|
+
requestStartedAt = CACurrentMediaTime()
|
|
262
278
|
onLoadStart?()
|
|
263
279
|
guard Self.isCurrentRequestGeneration(generation, current: requestGeneration) else { return }
|
|
280
|
+
if showMemoryCachedImageIfAvailable(requestIsActive: true) { return }
|
|
281
|
+
showLoading(requestIsActive: true, letLibraryStartIndicator: true)
|
|
264
282
|
|
|
265
283
|
if let violation = OneKeyImageSafetyPolicy.preflight(source: rawString) {
|
|
266
284
|
finishWithError(violation, generation: generation)
|
|
@@ -372,6 +390,8 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
372
390
|
self.skeletonIndicator.stopAnimatingIndicator()
|
|
373
391
|
self.fallbackLayer.isHidden = true
|
|
374
392
|
self.hostView.backgroundColor = .clear
|
|
393
|
+
let resolvedCacheType = Self.cacheType(cacheType)
|
|
394
|
+
self.applyLoadedImageTransition(cacheType: resolvedCacheType)
|
|
375
395
|
self.applyAutoplay()
|
|
376
396
|
let onLoad = self.onLoad
|
|
377
397
|
let onLoadEnd = self.onLoadEnd
|
|
@@ -380,7 +400,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
380
400
|
onLoad?(
|
|
381
401
|
Double(image?.size.width ?? 0),
|
|
382
402
|
Double(image?.size.height ?? 0),
|
|
383
|
-
|
|
403
|
+
resolvedCacheType
|
|
384
404
|
)
|
|
385
405
|
},
|
|
386
406
|
onLoadEnd: { onLoadEnd?() }
|
|
@@ -428,6 +448,8 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
428
448
|
activeSafetyHandle = nil
|
|
429
449
|
requestActive = false
|
|
430
450
|
skeletonIndicator.stopAnimatingIndicator()
|
|
451
|
+
requestStartedAt = nil
|
|
452
|
+
resetImageTransition()
|
|
431
453
|
if invalidateGeneration { requestGeneration &+= 1 }
|
|
432
454
|
}
|
|
433
455
|
|
|
@@ -474,6 +496,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
474
496
|
resizeWidth = nil
|
|
475
497
|
overscan = 1.1
|
|
476
498
|
loadingStrategy = .static
|
|
499
|
+
placeholderColor = nil
|
|
477
500
|
onLoadStart = nil
|
|
478
501
|
onLoad = nil
|
|
479
502
|
onDisplay = nil
|
|
@@ -498,11 +521,86 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
498
521
|
) {
|
|
499
522
|
displayState = .loading
|
|
500
523
|
requestActive = requestIsActive
|
|
524
|
+
resetImageTransition()
|
|
501
525
|
hostView.image = nil
|
|
502
526
|
fallbackLayer.isHidden = true
|
|
503
527
|
applyLoadingAppearance(letLibraryStartIndicator: letLibraryStartIndicator)
|
|
504
528
|
}
|
|
505
529
|
|
|
530
|
+
private func showMemoryCachedImageIfAvailable(requestIsActive: Bool) -> Bool {
|
|
531
|
+
guard cachePolicy == .memory || cachePolicy == .memoryDisk,
|
|
532
|
+
let sourceUri,
|
|
533
|
+
let rawURL = URL(string: sourceUri) else {
|
|
534
|
+
return false
|
|
535
|
+
}
|
|
536
|
+
let rawScreenScale: CGFloat = hostView.window?.screen.scale ?? UIScreen.main.scale
|
|
537
|
+
let screenScale = min(max(rawScreenScale, 1), 3)
|
|
538
|
+
let hasCustomIdentity = OneKeyImageRequestContext.headers(from: sourceHeadersJson) != nil
|
|
539
|
+
let displaySize = resizeWidth.flatMap { $0.isFinite && $0 > 0 ? CGFloat($0) : nil }
|
|
540
|
+
?? max(hostView.bounds.width, hostView.bounds.height)
|
|
541
|
+
let requestURL =
|
|
542
|
+
(optimizeTos ?? true)
|
|
543
|
+
? OneKeyTosURL.optimized(
|
|
544
|
+
rawURL: rawURL,
|
|
545
|
+
displaySize: displaySize,
|
|
546
|
+
scale: screenScale,
|
|
547
|
+
overscan: overscan ?? 1.1,
|
|
548
|
+
hasCustomIdentity: hasCustomIdentity
|
|
549
|
+
)
|
|
550
|
+
: rawURL
|
|
551
|
+
let thumbnailPixelSize = OneKeyImageDecodeSizing.thumbnailPixelSize(
|
|
552
|
+
viewSize: hostView.bounds.size,
|
|
553
|
+
scale: screenScale,
|
|
554
|
+
contentFit: contentFit ?? .cover
|
|
555
|
+
)
|
|
556
|
+
func memoryCachedImage(for url: URL) -> UIImage? {
|
|
557
|
+
let context = OneKeyImageRequestContext.make(
|
|
558
|
+
headersJson: sourceHeadersJson,
|
|
559
|
+
cachePolicy: cachePolicy ?? .memoryDisk,
|
|
560
|
+
thumbnailPixelSize: thumbnailPixelSize,
|
|
561
|
+
safetyTracker: nil,
|
|
562
|
+
manager: OneKeyImagePipeline.manager,
|
|
563
|
+
url: url
|
|
564
|
+
)
|
|
565
|
+
let cache = context[.imageCache] as? SDImageCache ?? SDImageCache.shared
|
|
566
|
+
guard let key = OneKeyImagePipeline.manager.cacheKey(for: url, context: context) else {
|
|
567
|
+
return nil
|
|
568
|
+
}
|
|
569
|
+
return cache.imageFromMemoryCache(forKey: key)
|
|
570
|
+
}
|
|
571
|
+
guard let image = memoryCachedImage(for: requestURL)
|
|
572
|
+
?? (requestURL == rawURL ? nil : memoryCachedImage(for: rawURL)) else {
|
|
573
|
+
return false
|
|
574
|
+
}
|
|
575
|
+
let generation = requestGeneration
|
|
576
|
+
if requestIsActive, !claimTerminal(generation) { return true }
|
|
577
|
+
displayState = .image
|
|
578
|
+
requestActive = false
|
|
579
|
+
skeletonIndicator.stopAnimatingIndicator()
|
|
580
|
+
fallbackLayer.isHidden = true
|
|
581
|
+
resetImageTransition()
|
|
582
|
+
hostView.image = image
|
|
583
|
+
hostView.backgroundColor = .clear
|
|
584
|
+
if requestIsActive {
|
|
585
|
+
applyLoadedImageTransition(cacheType: .memory)
|
|
586
|
+
}
|
|
587
|
+
applyAutoplay()
|
|
588
|
+
if requestIsActive {
|
|
589
|
+
let onLoad = onLoad
|
|
590
|
+
let onLoadEnd = onLoadEnd
|
|
591
|
+
Self.deliverTerminalCallbacks(
|
|
592
|
+
primary: {
|
|
593
|
+
onLoad?(Double(image.size.width), Double(image.size.height), .memory)
|
|
594
|
+
},
|
|
595
|
+
onLoadEnd: { onLoadEnd?() }
|
|
596
|
+
)
|
|
597
|
+
guard requestGeneration == generation else { return true }
|
|
598
|
+
pendingDisplayGeneration = generation
|
|
599
|
+
schedulePendingDisplayIfNeeded()
|
|
600
|
+
}
|
|
601
|
+
return true
|
|
602
|
+
}
|
|
603
|
+
|
|
506
604
|
private func showError() {
|
|
507
605
|
showTerminalState(.error)
|
|
508
606
|
}
|
|
@@ -515,13 +613,15 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
515
613
|
displayState = state
|
|
516
614
|
requestActive = false
|
|
517
615
|
skeletonIndicator.stopAnimatingIndicator()
|
|
616
|
+
resetImageTransition()
|
|
518
617
|
hostView.image = nil
|
|
519
|
-
|
|
618
|
+
let hidesTerminalState = loadingStrategy == .none
|
|
619
|
+
hostView.backgroundColor = hidesTerminalState ? .clear : resolvedPlaceholderColor
|
|
520
620
|
fallbackLayer.string = stateSymbol
|
|
521
621
|
fallbackLayer.fontSize = min(hostView.bounds.width, hostView.bounds.height) * 0.35
|
|
522
622
|
layoutFallbackLayer()
|
|
523
623
|
fallbackLayer.foregroundColor = UIColor.secondaryLabel.cgColor
|
|
524
|
-
fallbackLayer.isHidden =
|
|
624
|
+
fallbackLayer.isHidden = hidesTerminalState
|
|
525
625
|
}
|
|
526
626
|
|
|
527
627
|
private func applyVariant() {
|
|
@@ -531,22 +631,27 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
531
631
|
case .loading:
|
|
532
632
|
applyLoadingAppearance(letLibraryStartIndicator: false)
|
|
533
633
|
case .error, .fallback:
|
|
534
|
-
|
|
634
|
+
let hidesTerminalState = loadingStrategy == .none
|
|
635
|
+
hostView.backgroundColor = hidesTerminalState ? .clear : resolvedPlaceholderColor
|
|
535
636
|
fallbackLayer.string = stateSymbol
|
|
637
|
+
fallbackLayer.isHidden = hidesTerminalState
|
|
536
638
|
}
|
|
537
639
|
}
|
|
538
640
|
|
|
539
641
|
private func applyLoadingAppearance(letLibraryStartIndicator: Bool) {
|
|
540
642
|
let strategy = loadingStrategy ?? .static
|
|
541
|
-
hostView.backgroundColor = strategy == .none ? .clear :
|
|
643
|
+
hostView.backgroundColor = strategy == .none ? .clear : resolvedPlaceholderColor
|
|
542
644
|
|
|
543
645
|
if strategy == .skeleton {
|
|
646
|
+
skeletonIndicator.updateColors(skeletonGradientColors)
|
|
544
647
|
if hostView.sd_imageIndicator !== skeletonIndicator {
|
|
545
648
|
hostView.sd_imageIndicator = skeletonIndicator
|
|
546
649
|
}
|
|
547
650
|
skeletonIndicator.updateFrame(hostView.bounds)
|
|
548
|
-
if requestActive, !letLibraryStartIndicator {
|
|
651
|
+
if requestActive, !letLibraryStartIndicator, !UIAccessibility.isReduceMotionEnabled {
|
|
549
652
|
skeletonIndicator.startAnimatingIndicator()
|
|
653
|
+
} else if UIAccessibility.isReduceMotionEnabled {
|
|
654
|
+
skeletonIndicator.stopAnimatingIndicator()
|
|
550
655
|
}
|
|
551
656
|
} else {
|
|
552
657
|
skeletonIndicator.stopAnimatingIndicator()
|
|
@@ -566,13 +671,77 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
566
671
|
)
|
|
567
672
|
}
|
|
568
673
|
|
|
569
|
-
private var
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
case .
|
|
574
|
-
case .
|
|
674
|
+
private var resolvedPlaceholderColor: UIColor {
|
|
675
|
+
if let color = Self.color(from: placeholderColor) { return color }
|
|
676
|
+
// OneKey patch: fall back to a semantic system fill instead of a light-only color.
|
|
677
|
+
// switch variant ?? .generic {
|
|
678
|
+
// case .generic: return UIColor(white: 0.91, alpha: 1)
|
|
679
|
+
// case .token: return UIColor(red: 0.91, green: 0.93, blue: 0.98, alpha: 1)
|
|
680
|
+
// case .network: return UIColor(red: 0.90, green: 0.94, blue: 0.96, alpha: 1)
|
|
681
|
+
// case .avatar: return UIColor(red: 0.92, green: 0.92, blue: 0.94, alpha: 1)
|
|
682
|
+
// }
|
|
683
|
+
return .secondarySystemFill
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
private var skeletonGradientColors: [UIColor] {
|
|
687
|
+
let base = resolvedPlaceholderColor
|
|
688
|
+
let resolvedBase = base.resolvedColor(with: hostView.traitCollection)
|
|
689
|
+
var red: CGFloat = 0
|
|
690
|
+
var green: CGFloat = 0
|
|
691
|
+
var blue: CGFloat = 0
|
|
692
|
+
var alpha: CGFloat = 0
|
|
693
|
+
guard resolvedBase.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
|
|
694
|
+
return [base, base]
|
|
695
|
+
}
|
|
696
|
+
let average = (red + green + blue) / 3
|
|
697
|
+
let delta: CGFloat = average < 0.5 ? 18.0 / 255.0 : -12.0 / 255.0
|
|
698
|
+
let highlight = UIColor(
|
|
699
|
+
red: min(max(red + delta, 0), 1),
|
|
700
|
+
green: min(max(green + delta, 0), 1),
|
|
701
|
+
blue: min(max(blue + delta, 0), 1),
|
|
702
|
+
alpha: alpha
|
|
703
|
+
)
|
|
704
|
+
return [base, highlight]
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
private func applyLoadedImageTransition(cacheType: OneKeyImageCacheType) {
|
|
708
|
+
resetImageTransition()
|
|
709
|
+
guard cacheType != .memory,
|
|
710
|
+
let requestStartedAt,
|
|
711
|
+
CACurrentMediaTime() - requestStartedAt >= Self.fadeDelayThreshold,
|
|
712
|
+
!UIAccessibility.isReduceMotionEnabled else {
|
|
713
|
+
return
|
|
714
|
+
}
|
|
715
|
+
hostView.alpha = 0
|
|
716
|
+
UIView.animate(
|
|
717
|
+
withDuration: Self.fadeDuration,
|
|
718
|
+
delay: 0,
|
|
719
|
+
options: [.allowUserInteraction, .beginFromCurrentState, .curveEaseOut]
|
|
720
|
+
) {
|
|
721
|
+
self.hostView.alpha = 1
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
private func resetImageTransition() {
|
|
726
|
+
hostView.layer.removeAllAnimations()
|
|
727
|
+
hostView.alpha = 1
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
private static func color(from value: String?) -> UIColor? {
|
|
731
|
+
guard var hex = value?.trimmingCharacters(in: .whitespacesAndNewlines),
|
|
732
|
+
hex.hasPrefix("#") else {
|
|
733
|
+
return nil
|
|
734
|
+
}
|
|
735
|
+
hex.removeFirst()
|
|
736
|
+
guard hex.count == 6 || hex.count == 8,
|
|
737
|
+
let parsed = UInt64(hex, radix: 16) else {
|
|
738
|
+
return nil
|
|
575
739
|
}
|
|
740
|
+
let red = CGFloat((parsed >> (hex.count == 8 ? 24 : 16)) & 0xFF) / 255
|
|
741
|
+
let green = CGFloat((parsed >> (hex.count == 8 ? 16 : 8)) & 0xFF) / 255
|
|
742
|
+
let blue = CGFloat((parsed >> (hex.count == 8 ? 8 : 0)) & 0xFF) / 255
|
|
743
|
+
let alpha = hex.count == 8 ? CGFloat(parsed & 0xFF) / 255 : 1
|
|
744
|
+
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
|
|
576
745
|
}
|
|
577
746
|
|
|
578
747
|
private var stateSymbol: String {
|
|
@@ -28,6 +28,7 @@ public final class OneKeyImageReusableView: UIView {
|
|
|
28
28
|
optimizeTos: Bool,
|
|
29
29
|
overscan: Double,
|
|
30
30
|
loadingStrategy: String,
|
|
31
|
+
placeholderColor: String,
|
|
31
32
|
onLoad: (() -> Void)? = nil,
|
|
32
33
|
onError: (() -> Void)? = nil
|
|
33
34
|
) {
|
|
@@ -43,6 +44,7 @@ public final class OneKeyImageReusableView: UIView {
|
|
|
43
44
|
image.optimizeTos = optimizeTos
|
|
44
45
|
image.overscan = overscan
|
|
45
46
|
image.loadingStrategy = OneKeyImageLoadingStrategy(fromString: loadingStrategy) ?? .static
|
|
47
|
+
image.placeholderColor = placeholderColor
|
|
46
48
|
image.sourceUri = sourceUri
|
|
47
49
|
image.afterUpdate()
|
|
48
50
|
}
|
package/lib/module/index.js
CHANGED
|
@@ -47,6 +47,7 @@ export function OneKeyImage({
|
|
|
47
47
|
resizeWidth,
|
|
48
48
|
overscan = 1.1,
|
|
49
49
|
loadingStrategy = OneKeyImageLoadingStrategy.STATIC,
|
|
50
|
+
placeholderColor,
|
|
50
51
|
hybridRef,
|
|
51
52
|
onLoadStart,
|
|
52
53
|
onLoad,
|
|
@@ -176,7 +177,7 @@ export function OneKeyImage({
|
|
|
176
177
|
...viewProps,
|
|
177
178
|
...nativeCallbacks,
|
|
178
179
|
style: shouldWrapNative ? StyleSheet.absoluteFill : style,
|
|
179
|
-
sourceUri: normalized?.uri,
|
|
180
|
+
sourceUri: normalized?.uri ?? '',
|
|
180
181
|
sourceHeadersJson: normalized?.headers ? JSON.stringify(normalized.headers) : undefined,
|
|
181
182
|
variant,
|
|
182
183
|
contentFit,
|
|
@@ -186,7 +187,8 @@ export function OneKeyImage({
|
|
|
186
187
|
optimizeTos,
|
|
187
188
|
resizeWidth,
|
|
188
189
|
overscan,
|
|
189
|
-
loadingStrategy: placeholder == null ? loadingStrategy : OneKeyImageLoadingStrategy.NONE
|
|
190
|
+
loadingStrategy: placeholder == null ? loadingStrategy : OneKeyImageLoadingStrategy.NONE,
|
|
191
|
+
placeholderColor
|
|
190
192
|
});
|
|
191
193
|
if (!shouldWrapNative) return native;
|
|
192
194
|
return /*#__PURE__*/_jsxs(View, {
|
|
@@ -165,6 +165,15 @@ namespace margelo::nitro::onekeyimage {
|
|
|
165
165
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JOneKeyImageLoadingStrategy> /* loadingStrategy */)>("setLoadingStrategy");
|
|
166
166
|
method(_javaPart, loadingStrategy.has_value() ? JOneKeyImageLoadingStrategy::fromCpp(loadingStrategy.value()) : nullptr);
|
|
167
167
|
}
|
|
168
|
+
std::optional<std::string> JHybridOneKeyImageSpec::getPlaceholderColor() {
|
|
169
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getPlaceholderColor");
|
|
170
|
+
auto __result = method(_javaPart);
|
|
171
|
+
return __result != nullptr ? std::make_optional(__result->toStdString()) : std::nullopt;
|
|
172
|
+
}
|
|
173
|
+
void JHybridOneKeyImageSpec::setPlaceholderColor(const std::optional<std::string>& placeholderColor) {
|
|
174
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* placeholderColor */)>("setPlaceholderColor");
|
|
175
|
+
method(_javaPart, placeholderColor.has_value() ? jni::make_jstring(placeholderColor.value()) : nullptr);
|
|
176
|
+
}
|
|
168
177
|
std::optional<std::function<void()>> JHybridOneKeyImageSpec::getOnLoadStart() {
|
|
169
178
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JFunc_void::javaobject>()>("getOnLoadStart_cxx");
|
|
170
179
|
auto __result = method(_javaPart);
|
|
@@ -72,6 +72,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
72
72
|
void setOverscan(std::optional<double> overscan) override;
|
|
73
73
|
std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() override;
|
|
74
74
|
void setLoadingStrategy(std::optional<OneKeyImageLoadingStrategy> loadingStrategy) override;
|
|
75
|
+
std::optional<std::string> getPlaceholderColor() override;
|
|
76
|
+
void setPlaceholderColor(const std::optional<std::string>& placeholderColor) override;
|
|
75
77
|
std::optional<std::function<void()>> getOnLoadStart() override;
|
|
76
78
|
void setOnLoadStart(const std::optional<std::function<void()>>& onLoadStart) override;
|
|
77
79
|
std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>> getOnLoad() override;
|
|
@@ -108,6 +108,11 @@ void JHybridOneKeyImageStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
|
|
|
108
108
|
: !newProps->loadingStrategy.hasSameValue(oldProps->loadingStrategy)) {
|
|
109
109
|
hybridView->setLoadingStrategy(newProps->loadingStrategy.get());
|
|
110
110
|
}
|
|
111
|
+
if (oldProps == nullptr
|
|
112
|
+
? newProps->placeholderColor.isProvided()
|
|
113
|
+
: !newProps->placeholderColor.hasSameValue(oldProps->placeholderColor)) {
|
|
114
|
+
hybridView->setPlaceholderColor(newProps->placeholderColor.get());
|
|
115
|
+
}
|
|
111
116
|
if (oldProps == nullptr
|
|
112
117
|
? newProps->onLoadStart.isProvided()
|
|
113
118
|
: !newProps->onLoadStart.hasSameValue(oldProps->onLoadStart)) {
|
package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt
CHANGED
|
@@ -93,6 +93,12 @@ abstract class HybridOneKeyImageSpec: HybridView() {
|
|
|
93
93
|
@set:Keep
|
|
94
94
|
abstract var loadingStrategy: OneKeyImageLoadingStrategy?
|
|
95
95
|
|
|
96
|
+
@get:DoNotStrip
|
|
97
|
+
@get:Keep
|
|
98
|
+
@set:DoNotStrip
|
|
99
|
+
@set:Keep
|
|
100
|
+
abstract var placeholderColor: String?
|
|
101
|
+
|
|
96
102
|
abstract var onLoadStart: (() -> Unit)?
|
|
97
103
|
|
|
98
104
|
private var onLoadStart_cxx: Func_void?
|
|
@@ -155,6 +155,13 @@ namespace margelo::nitro::onekeyimage {
|
|
|
155
155
|
inline void setLoadingStrategy(std::optional<OneKeyImageLoadingStrategy> loadingStrategy) noexcept override {
|
|
156
156
|
_swiftPart.setLoadingStrategy(loadingStrategy);
|
|
157
157
|
}
|
|
158
|
+
inline std::optional<std::string> getPlaceholderColor() noexcept override {
|
|
159
|
+
auto __result = _swiftPart.getPlaceholderColor();
|
|
160
|
+
return __result;
|
|
161
|
+
}
|
|
162
|
+
inline void setPlaceholderColor(const std::optional<std::string>& placeholderColor) noexcept override {
|
|
163
|
+
_swiftPart.setPlaceholderColor(placeholderColor);
|
|
164
|
+
}
|
|
158
165
|
inline std::optional<std::function<void()>> getOnLoadStart() noexcept override {
|
|
159
166
|
auto __result = _swiftPart.getOnLoadStart();
|
|
160
167
|
return __result;
|
|
@@ -164,6 +164,12 @@ using namespace margelo::nitro::onekeyimage::views;
|
|
|
164
164
|
: !newViewProps.loadingStrategy.hasSameValue(oldViewProps->loadingStrategy)) {
|
|
165
165
|
swiftPart.setLoadingStrategy(newViewProps.loadingStrategy.get());
|
|
166
166
|
}
|
|
167
|
+
// placeholderColor: optional
|
|
168
|
+
if (oldViewProps == nullptr
|
|
169
|
+
? newViewProps.placeholderColor.isProvided()
|
|
170
|
+
: !newViewProps.placeholderColor.hasSameValue(oldViewProps->placeholderColor)) {
|
|
171
|
+
swiftPart.setPlaceholderColor(newViewProps.placeholderColor.get());
|
|
172
|
+
}
|
|
167
173
|
// onLoadStart: optional
|
|
168
174
|
if (oldViewProps == nullptr
|
|
169
175
|
? newViewProps.onLoadStart.isProvided()
|
|
@@ -21,6 +21,7 @@ public protocol HybridOneKeyImageSpec_protocol: HybridObject, HybridView {
|
|
|
21
21
|
var resizeWidth: Double? { get set }
|
|
22
22
|
var overscan: Double? { get set }
|
|
23
23
|
var loadingStrategy: OneKeyImageLoadingStrategy? { get set }
|
|
24
|
+
var placeholderColor: String? { get set }
|
|
24
25
|
var onLoadStart: (() -> Void)? { get set }
|
|
25
26
|
var onLoad: ((_ width: Double, _ height: Double, _ cacheType: OneKeyImageCacheType) -> Void)? { get set }
|
|
26
27
|
var onDisplay: (() -> Void)? { get set }
|
|
@@ -357,6 +357,30 @@ open class HybridOneKeyImageSpec_cxx {
|
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
+
public final var placeholderColor: bridge.std__optional_std__string_ {
|
|
361
|
+
@inline(__always)
|
|
362
|
+
get {
|
|
363
|
+
return { () -> bridge.std__optional_std__string_ in
|
|
364
|
+
if let __unwrappedValue = self.__implementation.placeholderColor {
|
|
365
|
+
return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
|
|
366
|
+
} else {
|
|
367
|
+
return .init()
|
|
368
|
+
}
|
|
369
|
+
}()
|
|
370
|
+
}
|
|
371
|
+
@inline(__always)
|
|
372
|
+
set {
|
|
373
|
+
self.__implementation.placeholderColor = { () -> String? in
|
|
374
|
+
if bridge.has_value_std__optional_std__string_(newValue) {
|
|
375
|
+
let __unwrapped = bridge.get_std__optional_std__string_(newValue)
|
|
376
|
+
return String(__unwrapped)
|
|
377
|
+
} else {
|
|
378
|
+
return nil
|
|
379
|
+
}
|
|
380
|
+
}()
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
360
384
|
public final var onLoadStart: bridge.std__optional_std__function_void____ {
|
|
361
385
|
@inline(__always)
|
|
362
386
|
get {
|
|
@@ -36,6 +36,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
36
36
|
prototype.registerHybridSetter("overscan", &HybridOneKeyImageSpec::setOverscan);
|
|
37
37
|
prototype.registerHybridGetter("loadingStrategy", &HybridOneKeyImageSpec::getLoadingStrategy);
|
|
38
38
|
prototype.registerHybridSetter("loadingStrategy", &HybridOneKeyImageSpec::setLoadingStrategy);
|
|
39
|
+
prototype.registerHybridGetter("placeholderColor", &HybridOneKeyImageSpec::getPlaceholderColor);
|
|
40
|
+
prototype.registerHybridSetter("placeholderColor", &HybridOneKeyImageSpec::setPlaceholderColor);
|
|
39
41
|
prototype.registerHybridGetter("onLoadStart", &HybridOneKeyImageSpec::getOnLoadStart);
|
|
40
42
|
prototype.registerHybridSetter("onLoadStart", &HybridOneKeyImageSpec::setOnLoadStart);
|
|
41
43
|
prototype.registerHybridGetter("onLoad", &HybridOneKeyImageSpec::getOnLoad);
|
|
@@ -82,6 +82,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
82
82
|
virtual void setOverscan(std::optional<double> overscan) = 0;
|
|
83
83
|
virtual std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() = 0;
|
|
84
84
|
virtual void setLoadingStrategy(std::optional<OneKeyImageLoadingStrategy> loadingStrategy) = 0;
|
|
85
|
+
virtual std::optional<std::string> getPlaceholderColor() = 0;
|
|
86
|
+
virtual void setPlaceholderColor(const std::optional<std::string>& placeholderColor) = 0;
|
|
85
87
|
virtual std::optional<std::function<void()>> getOnLoadStart() = 0;
|
|
86
88
|
virtual void setOnLoadStart(const std::optional<std::function<void()>>& onLoadStart) = 0;
|
|
87
89
|
virtual std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>> getOnLoad() = 0;
|
|
@@ -31,6 +31,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
31
31
|
resizeWidth(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeWidth", rawProps, sourceProps.resizeWidth)),
|
|
32
32
|
overscan(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "overscan", rawProps, sourceProps.overscan)),
|
|
33
33
|
loadingStrategy(nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>>::fromRawValue("OneKeyImage", "loadingStrategy", rawProps, sourceProps.loadingStrategy)),
|
|
34
|
+
placeholderColor(nitro::ReactProp<std::optional<std::string>>::fromRawValue("OneKeyImage", "placeholderColor", rawProps, sourceProps.placeholderColor)),
|
|
34
35
|
onLoadStart(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("OneKeyImage", "onLoadStart", rawProps, sourceProps.onLoadStart)),
|
|
35
36
|
onLoad(nitro::ReactProp<std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>>>::fromRawValue("OneKeyImage", "onLoad", rawProps, sourceProps.onLoad)),
|
|
36
37
|
onDisplay(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("OneKeyImage", "onDisplay", rawProps, sourceProps.onDisplay)),
|
|
@@ -51,6 +52,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
51
52
|
case hashString("resizeWidth"): return true;
|
|
52
53
|
case hashString("overscan"): return true;
|
|
53
54
|
case hashString("loadingStrategy"): return true;
|
|
55
|
+
case hashString("placeholderColor"): return true;
|
|
54
56
|
case hashString("onLoadStart"): return true;
|
|
55
57
|
case hashString("onLoad"): return true;
|
|
56
58
|
case hashString("onDisplay"): return true;
|
|
@@ -59,6 +59,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
59
59
|
nitro::ReactProp<std::optional<double>> resizeWidth;
|
|
60
60
|
nitro::ReactProp<std::optional<double>> overscan;
|
|
61
61
|
nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>> loadingStrategy;
|
|
62
|
+
nitro::ReactProp<std::optional<std::string>> placeholderColor;
|
|
62
63
|
nitro::ReactProp<std::optional<std::function<void()>>> onLoadStart;
|
|
63
64
|
nitro::ReactProp<std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>>> onLoad;
|
|
64
65
|
nitro::ReactProp<std::optional<std::function<void()>>> onDisplay;
|
|
@@ -79,6 +80,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
79
80
|
resizeWidth.hasSameValue(other.resizeWidth) &&
|
|
80
81
|
overscan.hasSameValue(other.overscan) &&
|
|
81
82
|
loadingStrategy.hasSameValue(other.loadingStrategy) &&
|
|
83
|
+
placeholderColor.hasSameValue(other.placeholderColor) &&
|
|
82
84
|
onLoadStart.hasSameValue(other.onLoadStart) &&
|
|
83
85
|
onLoad.hasSameValue(other.onLoad) &&
|
|
84
86
|
onDisplay.hasSameValue(other.onDisplay) &&
|
|
@@ -100,6 +102,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
100
102
|
resizeWidth.isProvided() ||
|
|
101
103
|
overscan.isProvided() ||
|
|
102
104
|
loadingStrategy.isProvided() ||
|
|
105
|
+
placeholderColor.isProvided() ||
|
|
103
106
|
onLoadStart.isProvided() ||
|
|
104
107
|
onLoad.isProvided() ||
|
|
105
108
|
onDisplay.isProvided() ||
|
|
@@ -36,6 +36,8 @@ export interface OneKeyImageNativeProps extends HybridViewProps {
|
|
|
36
36
|
resizeWidth?: number;
|
|
37
37
|
overscan?: number;
|
|
38
38
|
loadingStrategy?: OneKeyImageLoadingStrategy;
|
|
39
|
+
/** Theme-aware color used by static loading, error, and fallback states. */
|
|
40
|
+
placeholderColor?: string;
|
|
39
41
|
onLoadStart?: () => void;
|
|
40
42
|
onLoad?: (width: number, height: number, cacheType: OneKeyImageCacheType) => void;
|
|
41
43
|
onDisplay?: () => void;
|
|
@@ -45,7 +45,7 @@ export interface OneKeyImageProps extends Omit<OneKeyImageNativeProps, 'sourceUr
|
|
|
45
45
|
onError?: MaybeWrappedCallback<(event: OneKeyImageErrorEvent) => void>;
|
|
46
46
|
onLoadEnd?: MaybeWrappedCallback<() => void>;
|
|
47
47
|
}
|
|
48
|
-
export declare function OneKeyImage({ source, placeholder, fallback, variant, contentFit, cachePolicy, autoplay, recyclingKey, optimizeTos, resizeWidth, overscan, loadingStrategy, hybridRef, onLoadStart, onLoad, onDisplay, onError, onLoadEnd, style, ...viewProps }: OneKeyImageProps): import("react/jsx-runtime").JSX.Element;
|
|
48
|
+
export declare function OneKeyImage({ source, placeholder, fallback, variant, contentFit, cachePolicy, autoplay, recyclingKey, optimizeTos, resizeWidth, overscan, loadingStrategy, placeholderColor, hybridRef, onLoadStart, onLoad, onDisplay, onError, onLoadEnd, style, ...viewProps }: OneKeyImageProps): import("react/jsx-runtime").JSX.Element;
|
|
49
49
|
export declare const OneKeyImageCache: {
|
|
50
50
|
preload(sources: OneKeyImagePreloadInput[]): Promise<boolean>;
|
|
51
51
|
clearMemory: () => Promise<void>;
|
|
@@ -165,6 +165,15 @@ namespace margelo::nitro::onekeyimage {
|
|
|
165
165
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<JOneKeyImageLoadingStrategy> /* loadingStrategy */)>("setLoadingStrategy");
|
|
166
166
|
method(_javaPart, loadingStrategy.has_value() ? JOneKeyImageLoadingStrategy::fromCpp(loadingStrategy.value()) : nullptr);
|
|
167
167
|
}
|
|
168
|
+
std::optional<std::string> JHybridOneKeyImageSpec::getPlaceholderColor() {
|
|
169
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JString>()>("getPlaceholderColor");
|
|
170
|
+
auto __result = method(_javaPart);
|
|
171
|
+
return __result != nullptr ? std::make_optional(__result->toStdString()) : std::nullopt;
|
|
172
|
+
}
|
|
173
|
+
void JHybridOneKeyImageSpec::setPlaceholderColor(const std::optional<std::string>& placeholderColor) {
|
|
174
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* placeholderColor */)>("setPlaceholderColor");
|
|
175
|
+
method(_javaPart, placeholderColor.has_value() ? jni::make_jstring(placeholderColor.value()) : nullptr);
|
|
176
|
+
}
|
|
168
177
|
std::optional<std::function<void()>> JHybridOneKeyImageSpec::getOnLoadStart() {
|
|
169
178
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<JFunc_void::javaobject>()>("getOnLoadStart_cxx");
|
|
170
179
|
auto __result = method(_javaPart);
|
|
@@ -72,6 +72,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
72
72
|
void setOverscan(std::optional<double> overscan) override;
|
|
73
73
|
std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() override;
|
|
74
74
|
void setLoadingStrategy(std::optional<OneKeyImageLoadingStrategy> loadingStrategy) override;
|
|
75
|
+
std::optional<std::string> getPlaceholderColor() override;
|
|
76
|
+
void setPlaceholderColor(const std::optional<std::string>& placeholderColor) override;
|
|
75
77
|
std::optional<std::function<void()>> getOnLoadStart() override;
|
|
76
78
|
void setOnLoadStart(const std::optional<std::function<void()>>& onLoadStart) override;
|
|
77
79
|
std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>> getOnLoad() override;
|
|
@@ -108,6 +108,11 @@ void JHybridOneKeyImageStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
|
|
|
108
108
|
: !newProps->loadingStrategy.hasSameValue(oldProps->loadingStrategy)) {
|
|
109
109
|
hybridView->setLoadingStrategy(newProps->loadingStrategy.get());
|
|
110
110
|
}
|
|
111
|
+
if (oldProps == nullptr
|
|
112
|
+
? newProps->placeholderColor.isProvided()
|
|
113
|
+
: !newProps->placeholderColor.hasSameValue(oldProps->placeholderColor)) {
|
|
114
|
+
hybridView->setPlaceholderColor(newProps->placeholderColor.get());
|
|
115
|
+
}
|
|
111
116
|
if (oldProps == nullptr
|
|
112
117
|
? newProps->onLoadStart.isProvided()
|
|
113
118
|
: !newProps->onLoadStart.hasSameValue(oldProps->onLoadStart)) {
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt
CHANGED
|
@@ -93,6 +93,12 @@ abstract class HybridOneKeyImageSpec: HybridView() {
|
|
|
93
93
|
@set:Keep
|
|
94
94
|
abstract var loadingStrategy: OneKeyImageLoadingStrategy?
|
|
95
95
|
|
|
96
|
+
@get:DoNotStrip
|
|
97
|
+
@get:Keep
|
|
98
|
+
@set:DoNotStrip
|
|
99
|
+
@set:Keep
|
|
100
|
+
abstract var placeholderColor: String?
|
|
101
|
+
|
|
96
102
|
abstract var onLoadStart: (() -> Unit)?
|
|
97
103
|
|
|
98
104
|
private var onLoadStart_cxx: Func_void?
|
|
@@ -155,6 +155,13 @@ namespace margelo::nitro::onekeyimage {
|
|
|
155
155
|
inline void setLoadingStrategy(std::optional<OneKeyImageLoadingStrategy> loadingStrategy) noexcept override {
|
|
156
156
|
_swiftPart.setLoadingStrategy(loadingStrategy);
|
|
157
157
|
}
|
|
158
|
+
inline std::optional<std::string> getPlaceholderColor() noexcept override {
|
|
159
|
+
auto __result = _swiftPart.getPlaceholderColor();
|
|
160
|
+
return __result;
|
|
161
|
+
}
|
|
162
|
+
inline void setPlaceholderColor(const std::optional<std::string>& placeholderColor) noexcept override {
|
|
163
|
+
_swiftPart.setPlaceholderColor(placeholderColor);
|
|
164
|
+
}
|
|
158
165
|
inline std::optional<std::function<void()>> getOnLoadStart() noexcept override {
|
|
159
166
|
auto __result = _swiftPart.getOnLoadStart();
|
|
160
167
|
return __result;
|
|
@@ -164,6 +164,12 @@ using namespace margelo::nitro::onekeyimage::views;
|
|
|
164
164
|
: !newViewProps.loadingStrategy.hasSameValue(oldViewProps->loadingStrategy)) {
|
|
165
165
|
swiftPart.setLoadingStrategy(newViewProps.loadingStrategy.get());
|
|
166
166
|
}
|
|
167
|
+
// placeholderColor: optional
|
|
168
|
+
if (oldViewProps == nullptr
|
|
169
|
+
? newViewProps.placeholderColor.isProvided()
|
|
170
|
+
: !newViewProps.placeholderColor.hasSameValue(oldViewProps->placeholderColor)) {
|
|
171
|
+
swiftPart.setPlaceholderColor(newViewProps.placeholderColor.get());
|
|
172
|
+
}
|
|
167
173
|
// onLoadStart: optional
|
|
168
174
|
if (oldViewProps == nullptr
|
|
169
175
|
? newViewProps.onLoadStart.isProvided()
|
|
@@ -21,6 +21,7 @@ public protocol HybridOneKeyImageSpec_protocol: HybridObject, HybridView {
|
|
|
21
21
|
var resizeWidth: Double? { get set }
|
|
22
22
|
var overscan: Double? { get set }
|
|
23
23
|
var loadingStrategy: OneKeyImageLoadingStrategy? { get set }
|
|
24
|
+
var placeholderColor: String? { get set }
|
|
24
25
|
var onLoadStart: (() -> Void)? { get set }
|
|
25
26
|
var onLoad: ((_ width: Double, _ height: Double, _ cacheType: OneKeyImageCacheType) -> Void)? { get set }
|
|
26
27
|
var onDisplay: (() -> Void)? { get set }
|
|
@@ -357,6 +357,30 @@ open class HybridOneKeyImageSpec_cxx {
|
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
359
|
|
|
360
|
+
public final var placeholderColor: bridge.std__optional_std__string_ {
|
|
361
|
+
@inline(__always)
|
|
362
|
+
get {
|
|
363
|
+
return { () -> bridge.std__optional_std__string_ in
|
|
364
|
+
if let __unwrappedValue = self.__implementation.placeholderColor {
|
|
365
|
+
return bridge.create_std__optional_std__string_(std.string(__unwrappedValue))
|
|
366
|
+
} else {
|
|
367
|
+
return .init()
|
|
368
|
+
}
|
|
369
|
+
}()
|
|
370
|
+
}
|
|
371
|
+
@inline(__always)
|
|
372
|
+
set {
|
|
373
|
+
self.__implementation.placeholderColor = { () -> String? in
|
|
374
|
+
if bridge.has_value_std__optional_std__string_(newValue) {
|
|
375
|
+
let __unwrapped = bridge.get_std__optional_std__string_(newValue)
|
|
376
|
+
return String(__unwrapped)
|
|
377
|
+
} else {
|
|
378
|
+
return nil
|
|
379
|
+
}
|
|
380
|
+
}()
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
360
384
|
public final var onLoadStart: bridge.std__optional_std__function_void____ {
|
|
361
385
|
@inline(__always)
|
|
362
386
|
get {
|
|
@@ -36,6 +36,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
36
36
|
prototype.registerHybridSetter("overscan", &HybridOneKeyImageSpec::setOverscan);
|
|
37
37
|
prototype.registerHybridGetter("loadingStrategy", &HybridOneKeyImageSpec::getLoadingStrategy);
|
|
38
38
|
prototype.registerHybridSetter("loadingStrategy", &HybridOneKeyImageSpec::setLoadingStrategy);
|
|
39
|
+
prototype.registerHybridGetter("placeholderColor", &HybridOneKeyImageSpec::getPlaceholderColor);
|
|
40
|
+
prototype.registerHybridSetter("placeholderColor", &HybridOneKeyImageSpec::setPlaceholderColor);
|
|
39
41
|
prototype.registerHybridGetter("onLoadStart", &HybridOneKeyImageSpec::getOnLoadStart);
|
|
40
42
|
prototype.registerHybridSetter("onLoadStart", &HybridOneKeyImageSpec::setOnLoadStart);
|
|
41
43
|
prototype.registerHybridGetter("onLoad", &HybridOneKeyImageSpec::getOnLoad);
|
|
@@ -82,6 +82,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
82
82
|
virtual void setOverscan(std::optional<double> overscan) = 0;
|
|
83
83
|
virtual std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() = 0;
|
|
84
84
|
virtual void setLoadingStrategy(std::optional<OneKeyImageLoadingStrategy> loadingStrategy) = 0;
|
|
85
|
+
virtual std::optional<std::string> getPlaceholderColor() = 0;
|
|
86
|
+
virtual void setPlaceholderColor(const std::optional<std::string>& placeholderColor) = 0;
|
|
85
87
|
virtual std::optional<std::function<void()>> getOnLoadStart() = 0;
|
|
86
88
|
virtual void setOnLoadStart(const std::optional<std::function<void()>>& onLoadStart) = 0;
|
|
87
89
|
virtual std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>> getOnLoad() = 0;
|
|
@@ -31,6 +31,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
31
31
|
resizeWidth(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeWidth", rawProps, sourceProps.resizeWidth)),
|
|
32
32
|
overscan(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "overscan", rawProps, sourceProps.overscan)),
|
|
33
33
|
loadingStrategy(nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>>::fromRawValue("OneKeyImage", "loadingStrategy", rawProps, sourceProps.loadingStrategy)),
|
|
34
|
+
placeholderColor(nitro::ReactProp<std::optional<std::string>>::fromRawValue("OneKeyImage", "placeholderColor", rawProps, sourceProps.placeholderColor)),
|
|
34
35
|
onLoadStart(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("OneKeyImage", "onLoadStart", rawProps, sourceProps.onLoadStart)),
|
|
35
36
|
onLoad(nitro::ReactProp<std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>>>::fromRawValue("OneKeyImage", "onLoad", rawProps, sourceProps.onLoad)),
|
|
36
37
|
onDisplay(nitro::ReactProp<std::optional<std::function<void()>>>::fromRawValue("OneKeyImage", "onDisplay", rawProps, sourceProps.onDisplay)),
|
|
@@ -51,6 +52,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
51
52
|
case hashString("resizeWidth"): return true;
|
|
52
53
|
case hashString("overscan"): return true;
|
|
53
54
|
case hashString("loadingStrategy"): return true;
|
|
55
|
+
case hashString("placeholderColor"): return true;
|
|
54
56
|
case hashString("onLoadStart"): return true;
|
|
55
57
|
case hashString("onLoad"): return true;
|
|
56
58
|
case hashString("onDisplay"): return true;
|
|
@@ -59,6 +59,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
59
59
|
nitro::ReactProp<std::optional<double>> resizeWidth;
|
|
60
60
|
nitro::ReactProp<std::optional<double>> overscan;
|
|
61
61
|
nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>> loadingStrategy;
|
|
62
|
+
nitro::ReactProp<std::optional<std::string>> placeholderColor;
|
|
62
63
|
nitro::ReactProp<std::optional<std::function<void()>>> onLoadStart;
|
|
63
64
|
nitro::ReactProp<std::optional<std::function<void(double /* width */, double /* height */, OneKeyImageCacheType /* cacheType */)>>> onLoad;
|
|
64
65
|
nitro::ReactProp<std::optional<std::function<void()>>> onDisplay;
|
|
@@ -79,6 +80,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
79
80
|
resizeWidth.hasSameValue(other.resizeWidth) &&
|
|
80
81
|
overscan.hasSameValue(other.overscan) &&
|
|
81
82
|
loadingStrategy.hasSameValue(other.loadingStrategy) &&
|
|
83
|
+
placeholderColor.hasSameValue(other.placeholderColor) &&
|
|
82
84
|
onLoadStart.hasSameValue(other.onLoadStart) &&
|
|
83
85
|
onLoad.hasSameValue(other.onLoad) &&
|
|
84
86
|
onDisplay.hasSameValue(other.onDisplay) &&
|
|
@@ -100,6 +102,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
100
102
|
resizeWidth.isProvided() ||
|
|
101
103
|
overscan.isProvided() ||
|
|
102
104
|
loadingStrategy.isProvided() ||
|
|
105
|
+
placeholderColor.isProvided() ||
|
|
103
106
|
onLoadStart.isProvided() ||
|
|
104
107
|
onLoad.isProvided() ||
|
|
105
108
|
onDisplay.isProvided() ||
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-image",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.118",
|
|
4
4
|
"description": "High-performance native image view for OneKey",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"typescript": "^5.9.2"
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
|
-
"@onekeyfe/react-native-skeleton": "3.0.
|
|
84
|
+
"@onekeyfe/react-native-skeleton": "3.0.118",
|
|
85
85
|
"react": "*",
|
|
86
86
|
"react-native": "*",
|
|
87
87
|
"react-native-nitro-modules": "0.37.0"
|
package/src/OneKeyImage.nitro.ts
CHANGED
|
@@ -47,6 +47,8 @@ export interface OneKeyImageNativeProps extends HybridViewProps {
|
|
|
47
47
|
resizeWidth?: number;
|
|
48
48
|
overscan?: number;
|
|
49
49
|
loadingStrategy?: OneKeyImageLoadingStrategy;
|
|
50
|
+
/** Theme-aware color used by static loading, error, and fallback states. */
|
|
51
|
+
placeholderColor?: string;
|
|
50
52
|
onLoadStart?: () => void;
|
|
51
53
|
onLoad?: (
|
|
52
54
|
width: number,
|
package/src/index.tsx
CHANGED
|
@@ -156,6 +156,7 @@ export function OneKeyImage({
|
|
|
156
156
|
resizeWidth,
|
|
157
157
|
overscan = 1.1,
|
|
158
158
|
loadingStrategy = OneKeyImageLoadingStrategy.STATIC,
|
|
159
|
+
placeholderColor,
|
|
159
160
|
hybridRef,
|
|
160
161
|
onLoadStart,
|
|
161
162
|
onLoad,
|
|
@@ -329,7 +330,7 @@ export function OneKeyImage({
|
|
|
329
330
|
...viewProps,
|
|
330
331
|
...nativeCallbacks,
|
|
331
332
|
style: shouldWrapNative ? StyleSheet.absoluteFill : style,
|
|
332
|
-
sourceUri: normalized?.uri,
|
|
333
|
+
sourceUri: normalized?.uri ?? '',
|
|
333
334
|
sourceHeadersJson: normalized?.headers
|
|
334
335
|
? JSON.stringify(normalized.headers)
|
|
335
336
|
: undefined,
|
|
@@ -343,6 +344,7 @@ export function OneKeyImage({
|
|
|
343
344
|
overscan,
|
|
344
345
|
loadingStrategy:
|
|
345
346
|
placeholder == null ? loadingStrategy : OneKeyImageLoadingStrategy.NONE,
|
|
347
|
+
placeholderColor,
|
|
346
348
|
});
|
|
347
349
|
|
|
348
350
|
if (!shouldWrapNative) return native;
|