@onekeyfe/react-native-image 3.0.153 → 3.0.156

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImage.kt +64 -3
  2. package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageReusableView.kt +2 -0
  3. package/android/src/test/java/com/margelo/nitro/onekeyimage/OneKeyImageRequestSignatureTest.kt +14 -1
  4. package/ios/OneKeyImage.swift +19 -1
  5. package/ios/tests/OneKeyImageInfrastructureTests.swift +46 -0
  6. package/lib/module/index.js +2 -0
  7. package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.cpp +9 -0
  8. package/lib/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.hpp +2 -0
  9. package/lib/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.cpp +5 -0
  10. package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt +6 -0
  11. package/lib/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.hpp +7 -0
  12. package/lib/nitrogen/generated/ios/c++/views/HybridOneKeyImageComponent.mm +6 -0
  13. package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageSpec.swift +1 -0
  14. package/lib/nitrogen/generated/ios/swift/HybridOneKeyImageSpec_cxx.swift +24 -0
  15. package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.cpp +2 -0
  16. package/lib/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.hpp +2 -0
  17. package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.cpp +2 -0
  18. package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.hpp +3 -0
  19. package/lib/nitrogen/generated/shared/json/OneKeyImageConfig.json +1 -0
  20. package/lib/typescript/src/OneKeyImage.nitro.d.ts +2 -0
  21. package/lib/typescript/src/index.d.ts +1 -1
  22. package/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.cpp +9 -0
  23. package/nitrogen/generated/android/c++/JHybridOneKeyImageSpec.hpp +2 -0
  24. package/nitrogen/generated/android/c++/views/JHybridOneKeyImageStateUpdater.cpp +5 -0
  25. package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt +6 -0
  26. package/nitrogen/generated/ios/c++/HybridOneKeyImageSpecSwift.hpp +7 -0
  27. package/nitrogen/generated/ios/c++/views/HybridOneKeyImageComponent.mm +6 -0
  28. package/nitrogen/generated/ios/swift/HybridOneKeyImageSpec.swift +1 -0
  29. package/nitrogen/generated/ios/swift/HybridOneKeyImageSpec_cxx.swift +24 -0
  30. package/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.cpp +2 -0
  31. package/nitrogen/generated/shared/c++/HybridOneKeyImageSpec.hpp +2 -0
  32. package/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.cpp +2 -0
  33. package/nitrogen/generated/shared/c++/views/HybridOneKeyImageComponent.hpp +3 -0
  34. package/nitrogen/generated/shared/json/OneKeyImageConfig.json +1 -0
  35. package/package.json +2 -2
  36. package/src/OneKeyImage.nitro.ts +2 -0
  37. package/src/index.tsx +2 -0
@@ -7,7 +7,9 @@ import android.content.ContextWrapper
7
7
  import android.content.res.Configuration
8
8
  import android.graphics.Canvas
9
9
  import android.graphics.Color
10
+ import android.graphics.Outline
10
11
  import android.graphics.Paint
12
+ import android.graphics.Path
11
13
  import android.graphics.drawable.Animatable
12
14
  import android.graphics.drawable.Drawable
13
15
  import android.os.Build
@@ -15,6 +17,7 @@ import android.os.Looper
15
17
  import android.os.SystemClock
16
18
  import android.provider.Settings
17
19
  import android.view.View
20
+ import android.view.ViewOutlineProvider
18
21
  import android.view.animation.DecelerateInterpolator
19
22
  import android.widget.ImageView
20
23
  import com.bumptech.glide.Glide
@@ -44,6 +47,16 @@ private fun Context.findActivity(): Activity? {
44
47
  }
45
48
 
46
49
  private class OneKeyImageHostView(context: ThemedReactContext) : ImageView(context) {
50
+ private val roundClipPath = Path()
51
+ private val roundOutlineProvider = object : ViewOutlineProvider() {
52
+ override fun getOutline(view: View, outline: Outline) {
53
+ if (view.width > 0 && view.height > 0) {
54
+ outline.setOval(0, 0, view.width, view.height)
55
+ } else {
56
+ outline.setEmpty()
57
+ }
58
+ }
59
+ }
47
60
  private val fallbackPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
48
61
  color = Color.rgb(110, 110, 120)
49
62
  textAlign = Paint.Align.CENTER
@@ -52,6 +65,16 @@ private class OneKeyImageHostView(context: ThemedReactContext) : ImageView(conte
52
65
  var drawStateSymbol = false
53
66
  var stateSymbol = "◇"
54
67
  var autoplayEnabled = false
68
+ var round = false
69
+ set(value) {
70
+ if (field == value) return
71
+ field = value
72
+ outlineProvider = if (value) roundOutlineProvider else ViewOutlineProvider.BACKGROUND
73
+ clipToOutline = value
74
+ updateRoundClipPath()
75
+ invalidateOutline()
76
+ invalidate()
77
+ }
55
78
  private var aggregatedVisible = true
56
79
  var skeletonRequested = false
57
80
  set(value) {
@@ -65,9 +88,24 @@ private class OneKeyImageHostView(context: ThemedReactContext) : ImageView(conte
65
88
  super.onSizeChanged(w, h, oldw, oldh)
66
89
  skeleton.updateBounds(w, h)
67
90
  fallbackPaint.textSize = minOf(w, h) * 0.35f
91
+ if (round) {
92
+ updateRoundClipPath()
93
+ invalidateOutline()
94
+ }
68
95
  if (w > 0 && h > 0) onReadyForRequest?.invoke()
69
96
  }
70
97
 
98
+ override fun draw(canvas: Canvas) {
99
+ if (!round || roundClipPath.isEmpty) {
100
+ super.draw(canvas)
101
+ return
102
+ }
103
+ val saveCount = canvas.save()
104
+ canvas.clipPath(roundClipPath)
105
+ super.draw(canvas)
106
+ canvas.restoreToCount(saveCount)
107
+ }
108
+
71
109
  override fun onDraw(canvas: Canvas) {
72
110
  super.onDraw(canvas)
73
111
  if (drawStateSymbol) {
@@ -108,6 +146,13 @@ private class OneKeyImageHostView(context: ThemedReactContext) : ImageView(conte
108
146
  skeleton.updateBounds(width, height)
109
147
  }
110
148
 
149
+ private fun updateRoundClipPath() {
150
+ roundClipPath.reset()
151
+ if (round && width > 0 && height > 0) {
152
+ roundClipPath.addOval(0f, 0f, width.toFloat(), height.toFloat(), Path.Direction.CW)
153
+ }
154
+ }
155
+
111
156
  fun syncPlayback() {
112
157
  val canRun = isAttachedToWindow && aggregatedVisible
113
158
  if (skeletonRequested && canRun) skeleton.start() else skeleton.stop()
@@ -130,6 +175,7 @@ internal fun oneKeyImageRequestSignature(
130
175
  contentFit: OneKeyImageContentFit?,
131
176
  optimizeTos: Boolean?,
132
177
  overscan: Double?,
178
+ round: Boolean,
133
179
  width: Int,
134
180
  height: Int,
135
181
  density: Float,
@@ -142,6 +188,7 @@ internal fun oneKeyImageRequestSignature(
142
188
  (contentFit ?: OneKeyImageContentFit.COVER).name,
143
189
  optimizeTos.toString(),
144
190
  overscan.toString(),
191
+ round.toString(),
145
192
  resizeWidth.toString(),
146
193
  width.toString(),
147
194
  height.toString(),
@@ -241,6 +288,10 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
241
288
  field = value
242
289
  requestIdentityChanged()
243
290
  }
291
+ override var round: Boolean? = false
292
+ set(value) {
293
+ field = value
294
+ }
244
295
  override var overscan: Double? = 1.1
245
296
  set(value) {
246
297
  if (field == value) return
@@ -287,6 +338,10 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
287
338
 
288
339
  override fun afterUpdate() {
289
340
  super.afterUpdate()
341
+ // Fabric can reset `round` before clearing `sourceUri` while removing a view.
342
+ // Apply the shape once per committed prop batch so the outgoing frame keeps
343
+ // its clipping, while mounted and recycled views still receive the new value.
344
+ if (!sourceUri.isNullOrBlank()) hostView.round = round == true
290
345
  loadForCurrentLayout()
291
346
  }
292
347
 
@@ -346,6 +401,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
346
401
  autoplay = false
347
402
  recyclingKey = null
348
403
  optimizeTos = true
404
+ round = false
349
405
  resizeWidth = null
350
406
  overscan = 1.1
351
407
  loadingStrategy = OneKeyImageLoadingStrategy.STATIC
@@ -416,6 +472,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
416
472
  contentFit = contentFit,
417
473
  optimizeTos = optimizeTos,
418
474
  overscan = overscan,
475
+ round = round == true,
419
476
  width = hostView.width,
420
477
  height = hostView.height,
421
478
  density = hostView.resources.displayMetrics.density,
@@ -549,7 +606,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
549
606
  requestManager()
550
607
  .asDrawable()
551
608
  .load(OneKeyImageModel.build(requestUrl, headersJson))
552
- .apply(requestOptions(policy, requestUrl))
609
+ .apply(requestOptions(policy, requestUrl, round == true))
553
610
  .override(decodeDimensions.width, decodeDimensions.height)
554
611
  .listener(object : RequestListener<Drawable> {
555
612
  override fun onLoadFailed(
@@ -577,11 +634,15 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
577
634
  .into(target)
578
635
  }
579
636
 
580
- private fun requestOptions(policy: OneKeyImageCachePolicy, uri: String): RequestOptions {
637
+ private fun requestOptions(
638
+ policy: OneKeyImageCachePolicy,
639
+ uri: String,
640
+ round: Boolean,
641
+ ): RequestOptions {
581
642
  val options = RequestOptions()
582
643
  .withOneKeyAvatarCache(uri)
583
- .dontTransform()
584
644
  .downsample(OneKeyImageSafeDownsampleStrategy)
645
+ if (round) options.circleCrop() else options.dontTransform()
585
646
  return when (policy) {
586
647
  OneKeyImageCachePolicy.MEMORY_DISK -> options.diskCacheStrategy(oneKeyImageMemoryDiskStrategy(uri))
587
648
  OneKeyImageCachePolicy.MEMORY -> options.diskCacheStrategy(DiskCacheStrategy.NONE)
@@ -29,6 +29,7 @@ class OneKeyImageReusableView(context: ThemedReactContext) : FrameLayout(context
29
29
  overscan: Double,
30
30
  loadingStrategy: String,
31
31
  placeholderColor: String,
32
+ round: Boolean = false,
32
33
  onLoad: (() -> Unit)? = null,
33
34
  onError: (() -> Unit)? = null,
34
35
  ) {
@@ -57,6 +58,7 @@ class OneKeyImageReusableView(context: ThemedReactContext) : FrameLayout(context
57
58
  image.autoplay = autoplay
58
59
  image.recyclingKey = recyclingKey
59
60
  image.optimizeTos = optimizeTos
61
+ image.round = round
60
62
  image.overscan = overscan
61
63
  image.loadingStrategy = when (loadingStrategy) {
62
64
  "skeleton" -> OneKeyImageLoadingStrategy.SKELETON
@@ -26,7 +26,19 @@ class OneKeyImageRequestSignatureTest {
26
26
  )
27
27
  }
28
28
 
29
- private fun signature(contentFit: OneKeyImageContentFit?, resizeWidth: Double? = null): String = oneKeyImageRequestSignature(
29
+ @Test
30
+ fun roundParticipatesInRequestIdentity() {
31
+ assertNotEquals(
32
+ signature(OneKeyImageContentFit.COVER, round = false),
33
+ signature(OneKeyImageContentFit.COVER, round = true),
34
+ )
35
+ }
36
+
37
+ private fun signature(
38
+ contentFit: OneKeyImageContentFit?,
39
+ resizeWidth: Double? = null,
40
+ round: Boolean = false,
41
+ ): String = oneKeyImageRequestSignature(
30
42
  rawUrl = "https://example.com/image.png",
31
43
  sourceHeadersJson = null,
32
44
  recyclingKey = null,
@@ -34,6 +46,7 @@ class OneKeyImageRequestSignatureTest {
34
46
  contentFit = contentFit,
35
47
  optimizeTos = true,
36
48
  overscan = 1.1,
49
+ round = round,
37
50
  width = 200,
38
51
  height = 100,
39
52
  density = 2f,
@@ -7,9 +7,13 @@ import UIKit
7
7
  private final class OneKeyImageHostView: SDAnimatedImageView {
8
8
  var onLayout: (() -> Void)?
9
9
  var onWindowChanged: ((Bool) -> Void)?
10
+ var round = false {
11
+ didSet { updateRoundMask() }
12
+ }
10
13
 
11
14
  override func layoutSubviews() {
12
15
  super.layoutSubviews()
16
+ updateRoundMask()
13
17
  onLayout?()
14
18
  }
15
19
 
@@ -17,6 +21,10 @@ private final class OneKeyImageHostView: SDAnimatedImageView {
17
21
  super.didMoveToWindow()
18
22
  onWindowChanged?(window != nil)
19
23
  }
24
+
25
+ private func updateRoundMask() {
26
+ layer.cornerRadius = round ? min(bounds.width, bounds.height) / 2 : 0
27
+ }
20
28
  }
21
29
 
22
30
  private final class OneKeyImageSkeletonView: UIView {
@@ -112,7 +120,9 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
112
120
  var view: UIView { hostView }
113
121
 
114
122
  var sourceUri: String? {
115
- didSet { if sourceUri != oldValue { identityDidChange() } }
123
+ didSet {
124
+ if sourceUri != oldValue { identityDidChange() }
125
+ }
116
126
  }
117
127
  var sourceHeadersJson: String? {
118
128
  didSet { if sourceHeadersJson != oldValue { identityDidChange() } }
@@ -134,6 +144,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
134
144
  var optimizeTos: Bool? = true {
135
145
  didSet { if optimizeTos != oldValue { identityDidChange() } }
136
146
  }
147
+ var round: Bool? = false
137
148
  var resizeWidth: Double? {
138
149
  didSet {
139
150
  if !Self.equalOptionalDouble(resizeWidth, oldValue) { identityDidChange() }
@@ -185,6 +196,12 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
185
196
  }
186
197
 
187
198
  func afterUpdate() {
199
+ // Fabric can reset `round` before clearing `sourceUri` while removing a view.
200
+ // Apply the shape once per committed prop batch so the outgoing frame keeps
201
+ // its clipping, while mounted and recycled views still receive the new value.
202
+ if let sourceUri, !sourceUri.isEmpty {
203
+ hostView.round = round == true
204
+ }
188
205
  scheduleLoad()
189
206
  }
190
207
 
@@ -498,6 +515,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
498
515
  autoplay = true
499
516
  recyclingKey = nil
500
517
  optimizeTos = true
518
+ round = false
501
519
  resizeWidth = nil
502
520
  overscan = 1.1
503
521
  loadingStrategy = .static
@@ -565,4 +565,50 @@ final class OneKeyImageInfrastructureTests: XCTestCase {
565
565
  )
566
566
  XCTAssertTrue(imageView.clearBufferWhenStopped)
567
567
  }
568
+
569
+ func testRoundPropUpdatesNativeCornerRadius() throws {
570
+ let image = HybridOneKeyImage()
571
+ let imageView = try XCTUnwrap(image.view as? SDAnimatedImageView)
572
+ imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
573
+
574
+ image.sourceUri = "https://example.com/round.png"
575
+ image.round = true
576
+ image.afterUpdate()
577
+ imageView.layoutIfNeeded()
578
+ XCTAssertEqual(imageView.layer.cornerRadius, 20)
579
+
580
+ image.round = nil
581
+ image.afterUpdate()
582
+ XCTAssertEqual(imageView.layer.cornerRadius, 20)
583
+
584
+ image.round = false
585
+ image.afterUpdate()
586
+ XCTAssertEqual(imageView.layer.cornerRadius, 0)
587
+ }
588
+
589
+ func testRecycleKeepsRoundMaskUntilVisibleViewDetaches() throws {
590
+ let window = UIWindow(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
591
+ let image = HybridOneKeyImage()
592
+ let imageView = try XCTUnwrap(image.view as? SDAnimatedImageView)
593
+ imageView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
594
+ window.addSubview(imageView)
595
+ image.sourceUri = "https://example.com/round.png"
596
+ image.round = true
597
+ image.afterUpdate()
598
+ imageView.layoutIfNeeded()
599
+
600
+ // Fabric resets props in setter order before the view leaves the hierarchy.
601
+ image.round = false
602
+ image.sourceUri = nil
603
+ image.afterUpdate()
604
+ XCTAssertEqual(imageView.layer.cornerRadius, 20)
605
+
606
+ image.prepareForRecycle()
607
+
608
+ XCTAssertEqual(imageView.layer.cornerRadius, 20)
609
+
610
+ image.sourceUri = "https://example.com/reused.png"
611
+ image.afterUpdate()
612
+ XCTAssertEqual(imageView.layer.cornerRadius, 0)
613
+ }
568
614
  }
@@ -44,6 +44,7 @@ export function OneKeyImage({
44
44
  autoplay,
45
45
  recyclingKey,
46
46
  optimizeTos = true,
47
+ round = false,
47
48
  resizeWidth,
48
49
  overscan = 1.1,
49
50
  loadingStrategy = OneKeyImageLoadingStrategy.STATIC,
@@ -212,6 +213,7 @@ export function OneKeyImage({
212
213
  autoplay: autoplay ?? Platform.OS !== 'android',
213
214
  recyclingKey,
214
215
  optimizeTos,
216
+ round,
215
217
  resizeWidth,
216
218
  overscan,
217
219
  loadingStrategy: placeholder == null ? loadingStrategy : OneKeyImageLoadingStrategy.NONE,
@@ -138,6 +138,15 @@ namespace margelo::nitro::onekeyimage {
138
138
  static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JBoolean> /* optimizeTos */)>("setOptimizeTos");
139
139
  method(_javaPart, optimizeTos.has_value() ? jni::JBoolean::valueOf(optimizeTos.value()) : nullptr);
140
140
  }
141
+ std::optional<bool> JHybridOneKeyImageSpec::getRound() {
142
+ static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JBoolean>()>("getRound");
143
+ auto __result = method(_javaPart);
144
+ return __result != nullptr ? std::make_optional(static_cast<bool>(__result->value())) : std::nullopt;
145
+ }
146
+ void JHybridOneKeyImageSpec::setRound(std::optional<bool> round) {
147
+ static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JBoolean> /* round */)>("setRound");
148
+ method(_javaPart, round.has_value() ? jni::JBoolean::valueOf(round.value()) : nullptr);
149
+ }
141
150
  std::optional<double> JHybridOneKeyImageSpec::getResizeWidth() {
142
151
  static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getResizeWidth");
143
152
  auto __result = method(_javaPart);
@@ -66,6 +66,8 @@ namespace margelo::nitro::onekeyimage {
66
66
  void setRecyclingKey(const std::optional<std::string>& recyclingKey) override;
67
67
  std::optional<bool> getOptimizeTos() override;
68
68
  void setOptimizeTos(std::optional<bool> optimizeTos) override;
69
+ std::optional<bool> getRound() override;
70
+ void setRound(std::optional<bool> round) override;
69
71
  std::optional<double> getResizeWidth() override;
70
72
  void setResizeWidth(std::optional<double> resizeWidth) override;
71
73
  std::optional<double> getOverscan() override;
@@ -93,6 +93,11 @@ void JHybridOneKeyImageStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
93
93
  : !newProps->optimizeTos.hasSameValue(oldProps->optimizeTos)) {
94
94
  hybridView->setOptimizeTos(newProps->optimizeTos.get());
95
95
  }
96
+ if (oldProps == nullptr
97
+ ? newProps->round.isProvided()
98
+ : !newProps->round.hasSameValue(oldProps->round)) {
99
+ hybridView->setRound(newProps->round.get());
100
+ }
96
101
  if (oldProps == nullptr
97
102
  ? newProps->resizeWidth.isProvided()
98
103
  : !newProps->resizeWidth.hasSameValue(oldProps->resizeWidth)) {
@@ -75,6 +75,12 @@ abstract class HybridOneKeyImageSpec: HybridView() {
75
75
  @set:Keep
76
76
  abstract var optimizeTos: Boolean?
77
77
 
78
+ @get:DoNotStrip
79
+ @get:Keep
80
+ @set:DoNotStrip
81
+ @set:Keep
82
+ abstract var round: Boolean?
83
+
78
84
  @get:DoNotStrip
79
85
  @get:Keep
80
86
  @set:DoNotStrip
@@ -134,6 +134,13 @@ namespace margelo::nitro::onekeyimage {
134
134
  inline void setOptimizeTos(std::optional<bool> optimizeTos) noexcept override {
135
135
  _swiftPart.setOptimizeTos(optimizeTos);
136
136
  }
137
+ inline std::optional<bool> getRound() noexcept override {
138
+ auto __result = _swiftPart.getRound();
139
+ return __result;
140
+ }
141
+ inline void setRound(std::optional<bool> round) noexcept override {
142
+ _swiftPart.setRound(round);
143
+ }
137
144
  inline std::optional<double> getResizeWidth() noexcept override {
138
145
  auto __result = _swiftPart.getResizeWidth();
139
146
  return __result;
@@ -146,6 +146,12 @@ using namespace margelo::nitro::onekeyimage::views;
146
146
  : !newViewProps.optimizeTos.hasSameValue(oldViewProps->optimizeTos)) {
147
147
  swiftPart.setOptimizeTos(newViewProps.optimizeTos.get());
148
148
  }
149
+ // round: optional
150
+ if (oldViewProps == nullptr
151
+ ? newViewProps.round.isProvided()
152
+ : !newViewProps.round.hasSameValue(oldViewProps->round)) {
153
+ swiftPart.setRound(newViewProps.round.get());
154
+ }
149
155
  // resizeWidth: optional
150
156
  if (oldViewProps == nullptr
151
157
  ? newViewProps.resizeWidth.isProvided()
@@ -18,6 +18,7 @@ public protocol HybridOneKeyImageSpec_protocol: HybridObject, HybridView {
18
18
  var autoplay: Bool? { get set }
19
19
  var recyclingKey: String? { get set }
20
20
  var optimizeTos: Bool? { get set }
21
+ var round: Bool? { get set }
21
22
  var resizeWidth: Double? { get set }
22
23
  var overscan: Double? { get set }
23
24
  var loadingStrategy: OneKeyImageLoadingStrategy? { get set }
@@ -292,6 +292,30 @@ open class HybridOneKeyImageSpec_cxx {
292
292
  }
293
293
  }
294
294
 
295
+ public final var round: bridge.std__optional_bool_ {
296
+ @inline(__always)
297
+ get {
298
+ return { () -> bridge.std__optional_bool_ in
299
+ if let __unwrappedValue = self.__implementation.round {
300
+ return bridge.create_std__optional_bool_(__unwrappedValue)
301
+ } else {
302
+ return .init()
303
+ }
304
+ }()
305
+ }
306
+ @inline(__always)
307
+ set {
308
+ self.__implementation.round = { () -> Bool? in
309
+ if bridge.has_value_std__optional_bool_(newValue) {
310
+ let __unwrapped = bridge.get_std__optional_bool_(newValue)
311
+ return __unwrapped
312
+ } else {
313
+ return nil
314
+ }
315
+ }()
316
+ }
317
+ }
318
+
295
319
  public final var resizeWidth: bridge.std__optional_double_ {
296
320
  @inline(__always)
297
321
  get {
@@ -30,6 +30,8 @@ namespace margelo::nitro::onekeyimage {
30
30
  prototype.registerHybridSetter("recyclingKey", &HybridOneKeyImageSpec::setRecyclingKey);
31
31
  prototype.registerHybridGetter("optimizeTos", &HybridOneKeyImageSpec::getOptimizeTos);
32
32
  prototype.registerHybridSetter("optimizeTos", &HybridOneKeyImageSpec::setOptimizeTos);
33
+ prototype.registerHybridGetter("round", &HybridOneKeyImageSpec::getRound);
34
+ prototype.registerHybridSetter("round", &HybridOneKeyImageSpec::setRound);
33
35
  prototype.registerHybridGetter("resizeWidth", &HybridOneKeyImageSpec::getResizeWidth);
34
36
  prototype.registerHybridSetter("resizeWidth", &HybridOneKeyImageSpec::setResizeWidth);
35
37
  prototype.registerHybridGetter("overscan", &HybridOneKeyImageSpec::getOverscan);
@@ -76,6 +76,8 @@ namespace margelo::nitro::onekeyimage {
76
76
  virtual void setRecyclingKey(const std::optional<std::string>& recyclingKey) = 0;
77
77
  virtual std::optional<bool> getOptimizeTos() = 0;
78
78
  virtual void setOptimizeTos(std::optional<bool> optimizeTos) = 0;
79
+ virtual std::optional<bool> getRound() = 0;
80
+ virtual void setRound(std::optional<bool> round) = 0;
79
81
  virtual std::optional<double> getResizeWidth() = 0;
80
82
  virtual void setResizeWidth(std::optional<double> resizeWidth) = 0;
81
83
  virtual std::optional<double> getOverscan() = 0;
@@ -28,6 +28,7 @@ namespace margelo::nitro::onekeyimage::views {
28
28
  autoplay(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "autoplay", rawProps, sourceProps.autoplay)),
29
29
  recyclingKey(nitro::ReactProp<std::optional<std::string>>::fromRawValue("OneKeyImage", "recyclingKey", rawProps, sourceProps.recyclingKey)),
30
30
  optimizeTos(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "optimizeTos", rawProps, sourceProps.optimizeTos)),
31
+ round(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "round", rawProps, sourceProps.round)),
31
32
  resizeWidth(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeWidth", rawProps, sourceProps.resizeWidth)),
32
33
  overscan(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "overscan", rawProps, sourceProps.overscan)),
33
34
  loadingStrategy(nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>>::fromRawValue("OneKeyImage", "loadingStrategy", rawProps, sourceProps.loadingStrategy)),
@@ -49,6 +50,7 @@ namespace margelo::nitro::onekeyimage::views {
49
50
  case hashString("autoplay"): return true;
50
51
  case hashString("recyclingKey"): return true;
51
52
  case hashString("optimizeTos"): return true;
53
+ case hashString("round"): return true;
52
54
  case hashString("resizeWidth"): return true;
53
55
  case hashString("overscan"): return true;
54
56
  case hashString("loadingStrategy"): return true;
@@ -56,6 +56,7 @@ namespace margelo::nitro::onekeyimage::views {
56
56
  nitro::ReactProp<std::optional<bool>> autoplay;
57
57
  nitro::ReactProp<std::optional<std::string>> recyclingKey;
58
58
  nitro::ReactProp<std::optional<bool>> optimizeTos;
59
+ nitro::ReactProp<std::optional<bool>> round;
59
60
  nitro::ReactProp<std::optional<double>> resizeWidth;
60
61
  nitro::ReactProp<std::optional<double>> overscan;
61
62
  nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>> loadingStrategy;
@@ -77,6 +78,7 @@ namespace margelo::nitro::onekeyimage::views {
77
78
  autoplay.hasSameValue(other.autoplay) &&
78
79
  recyclingKey.hasSameValue(other.recyclingKey) &&
79
80
  optimizeTos.hasSameValue(other.optimizeTos) &&
81
+ round.hasSameValue(other.round) &&
80
82
  resizeWidth.hasSameValue(other.resizeWidth) &&
81
83
  overscan.hasSameValue(other.overscan) &&
82
84
  loadingStrategy.hasSameValue(other.loadingStrategy) &&
@@ -99,6 +101,7 @@ namespace margelo::nitro::onekeyimage::views {
99
101
  autoplay.isProvided() ||
100
102
  recyclingKey.isProvided() ||
101
103
  optimizeTos.isProvided() ||
104
+ round.isProvided() ||
102
105
  resizeWidth.isProvided() ||
103
106
  overscan.isProvided() ||
104
107
  loadingStrategy.isProvided() ||
@@ -12,6 +12,7 @@
12
12
  "autoplay": true,
13
13
  "recyclingKey": true,
14
14
  "optimizeTos": true,
15
+ "round": true,
15
16
  "resizeWidth": true,
16
17
  "overscan": true,
17
18
  "loadingStrategy": true,
@@ -32,6 +32,8 @@ export interface OneKeyImageNativeProps extends HybridViewProps {
32
32
  autoplay?: boolean;
33
33
  recyclingKey?: string;
34
34
  optimizeTos?: boolean;
35
+ /** Clips the native image to an oval using its current bounds. */
36
+ round?: boolean;
35
37
  /** Display width hint in layout units. Native applies the screen density. */
36
38
  resizeWidth?: number;
37
39
  overscan?: number;
@@ -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, placeholderColor, 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, round, 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>;
@@ -138,6 +138,15 @@ namespace margelo::nitro::onekeyimage {
138
138
  static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JBoolean> /* optimizeTos */)>("setOptimizeTos");
139
139
  method(_javaPart, optimizeTos.has_value() ? jni::JBoolean::valueOf(optimizeTos.value()) : nullptr);
140
140
  }
141
+ std::optional<bool> JHybridOneKeyImageSpec::getRound() {
142
+ static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JBoolean>()>("getRound");
143
+ auto __result = method(_javaPart);
144
+ return __result != nullptr ? std::make_optional(static_cast<bool>(__result->value())) : std::nullopt;
145
+ }
146
+ void JHybridOneKeyImageSpec::setRound(std::optional<bool> round) {
147
+ static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JBoolean> /* round */)>("setRound");
148
+ method(_javaPart, round.has_value() ? jni::JBoolean::valueOf(round.value()) : nullptr);
149
+ }
141
150
  std::optional<double> JHybridOneKeyImageSpec::getResizeWidth() {
142
151
  static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getResizeWidth");
143
152
  auto __result = method(_javaPart);
@@ -66,6 +66,8 @@ namespace margelo::nitro::onekeyimage {
66
66
  void setRecyclingKey(const std::optional<std::string>& recyclingKey) override;
67
67
  std::optional<bool> getOptimizeTos() override;
68
68
  void setOptimizeTos(std::optional<bool> optimizeTos) override;
69
+ std::optional<bool> getRound() override;
70
+ void setRound(std::optional<bool> round) override;
69
71
  std::optional<double> getResizeWidth() override;
70
72
  void setResizeWidth(std::optional<double> resizeWidth) override;
71
73
  std::optional<double> getOverscan() override;
@@ -93,6 +93,11 @@ void JHybridOneKeyImageStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
93
93
  : !newProps->optimizeTos.hasSameValue(oldProps->optimizeTos)) {
94
94
  hybridView->setOptimizeTos(newProps->optimizeTos.get());
95
95
  }
96
+ if (oldProps == nullptr
97
+ ? newProps->round.isProvided()
98
+ : !newProps->round.hasSameValue(oldProps->round)) {
99
+ hybridView->setRound(newProps->round.get());
100
+ }
96
101
  if (oldProps == nullptr
97
102
  ? newProps->resizeWidth.isProvided()
98
103
  : !newProps->resizeWidth.hasSameValue(oldProps->resizeWidth)) {
@@ -75,6 +75,12 @@ abstract class HybridOneKeyImageSpec: HybridView() {
75
75
  @set:Keep
76
76
  abstract var optimizeTos: Boolean?
77
77
 
78
+ @get:DoNotStrip
79
+ @get:Keep
80
+ @set:DoNotStrip
81
+ @set:Keep
82
+ abstract var round: Boolean?
83
+
78
84
  @get:DoNotStrip
79
85
  @get:Keep
80
86
  @set:DoNotStrip
@@ -134,6 +134,13 @@ namespace margelo::nitro::onekeyimage {
134
134
  inline void setOptimizeTos(std::optional<bool> optimizeTos) noexcept override {
135
135
  _swiftPart.setOptimizeTos(optimizeTos);
136
136
  }
137
+ inline std::optional<bool> getRound() noexcept override {
138
+ auto __result = _swiftPart.getRound();
139
+ return __result;
140
+ }
141
+ inline void setRound(std::optional<bool> round) noexcept override {
142
+ _swiftPart.setRound(round);
143
+ }
137
144
  inline std::optional<double> getResizeWidth() noexcept override {
138
145
  auto __result = _swiftPart.getResizeWidth();
139
146
  return __result;
@@ -146,6 +146,12 @@ using namespace margelo::nitro::onekeyimage::views;
146
146
  : !newViewProps.optimizeTos.hasSameValue(oldViewProps->optimizeTos)) {
147
147
  swiftPart.setOptimizeTos(newViewProps.optimizeTos.get());
148
148
  }
149
+ // round: optional
150
+ if (oldViewProps == nullptr
151
+ ? newViewProps.round.isProvided()
152
+ : !newViewProps.round.hasSameValue(oldViewProps->round)) {
153
+ swiftPart.setRound(newViewProps.round.get());
154
+ }
149
155
  // resizeWidth: optional
150
156
  if (oldViewProps == nullptr
151
157
  ? newViewProps.resizeWidth.isProvided()
@@ -18,6 +18,7 @@ public protocol HybridOneKeyImageSpec_protocol: HybridObject, HybridView {
18
18
  var autoplay: Bool? { get set }
19
19
  var recyclingKey: String? { get set }
20
20
  var optimizeTos: Bool? { get set }
21
+ var round: Bool? { get set }
21
22
  var resizeWidth: Double? { get set }
22
23
  var overscan: Double? { get set }
23
24
  var loadingStrategy: OneKeyImageLoadingStrategy? { get set }
@@ -292,6 +292,30 @@ open class HybridOneKeyImageSpec_cxx {
292
292
  }
293
293
  }
294
294
 
295
+ public final var round: bridge.std__optional_bool_ {
296
+ @inline(__always)
297
+ get {
298
+ return { () -> bridge.std__optional_bool_ in
299
+ if let __unwrappedValue = self.__implementation.round {
300
+ return bridge.create_std__optional_bool_(__unwrappedValue)
301
+ } else {
302
+ return .init()
303
+ }
304
+ }()
305
+ }
306
+ @inline(__always)
307
+ set {
308
+ self.__implementation.round = { () -> Bool? in
309
+ if bridge.has_value_std__optional_bool_(newValue) {
310
+ let __unwrapped = bridge.get_std__optional_bool_(newValue)
311
+ return __unwrapped
312
+ } else {
313
+ return nil
314
+ }
315
+ }()
316
+ }
317
+ }
318
+
295
319
  public final var resizeWidth: bridge.std__optional_double_ {
296
320
  @inline(__always)
297
321
  get {
@@ -30,6 +30,8 @@ namespace margelo::nitro::onekeyimage {
30
30
  prototype.registerHybridSetter("recyclingKey", &HybridOneKeyImageSpec::setRecyclingKey);
31
31
  prototype.registerHybridGetter("optimizeTos", &HybridOneKeyImageSpec::getOptimizeTos);
32
32
  prototype.registerHybridSetter("optimizeTos", &HybridOneKeyImageSpec::setOptimizeTos);
33
+ prototype.registerHybridGetter("round", &HybridOneKeyImageSpec::getRound);
34
+ prototype.registerHybridSetter("round", &HybridOneKeyImageSpec::setRound);
33
35
  prototype.registerHybridGetter("resizeWidth", &HybridOneKeyImageSpec::getResizeWidth);
34
36
  prototype.registerHybridSetter("resizeWidth", &HybridOneKeyImageSpec::setResizeWidth);
35
37
  prototype.registerHybridGetter("overscan", &HybridOneKeyImageSpec::getOverscan);
@@ -76,6 +76,8 @@ namespace margelo::nitro::onekeyimage {
76
76
  virtual void setRecyclingKey(const std::optional<std::string>& recyclingKey) = 0;
77
77
  virtual std::optional<bool> getOptimizeTos() = 0;
78
78
  virtual void setOptimizeTos(std::optional<bool> optimizeTos) = 0;
79
+ virtual std::optional<bool> getRound() = 0;
80
+ virtual void setRound(std::optional<bool> round) = 0;
79
81
  virtual std::optional<double> getResizeWidth() = 0;
80
82
  virtual void setResizeWidth(std::optional<double> resizeWidth) = 0;
81
83
  virtual std::optional<double> getOverscan() = 0;
@@ -28,6 +28,7 @@ namespace margelo::nitro::onekeyimage::views {
28
28
  autoplay(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "autoplay", rawProps, sourceProps.autoplay)),
29
29
  recyclingKey(nitro::ReactProp<std::optional<std::string>>::fromRawValue("OneKeyImage", "recyclingKey", rawProps, sourceProps.recyclingKey)),
30
30
  optimizeTos(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "optimizeTos", rawProps, sourceProps.optimizeTos)),
31
+ round(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "round", rawProps, sourceProps.round)),
31
32
  resizeWidth(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeWidth", rawProps, sourceProps.resizeWidth)),
32
33
  overscan(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "overscan", rawProps, sourceProps.overscan)),
33
34
  loadingStrategy(nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>>::fromRawValue("OneKeyImage", "loadingStrategy", rawProps, sourceProps.loadingStrategy)),
@@ -49,6 +50,7 @@ namespace margelo::nitro::onekeyimage::views {
49
50
  case hashString("autoplay"): return true;
50
51
  case hashString("recyclingKey"): return true;
51
52
  case hashString("optimizeTos"): return true;
53
+ case hashString("round"): return true;
52
54
  case hashString("resizeWidth"): return true;
53
55
  case hashString("overscan"): return true;
54
56
  case hashString("loadingStrategy"): return true;
@@ -56,6 +56,7 @@ namespace margelo::nitro::onekeyimage::views {
56
56
  nitro::ReactProp<std::optional<bool>> autoplay;
57
57
  nitro::ReactProp<std::optional<std::string>> recyclingKey;
58
58
  nitro::ReactProp<std::optional<bool>> optimizeTos;
59
+ nitro::ReactProp<std::optional<bool>> round;
59
60
  nitro::ReactProp<std::optional<double>> resizeWidth;
60
61
  nitro::ReactProp<std::optional<double>> overscan;
61
62
  nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>> loadingStrategy;
@@ -77,6 +78,7 @@ namespace margelo::nitro::onekeyimage::views {
77
78
  autoplay.hasSameValue(other.autoplay) &&
78
79
  recyclingKey.hasSameValue(other.recyclingKey) &&
79
80
  optimizeTos.hasSameValue(other.optimizeTos) &&
81
+ round.hasSameValue(other.round) &&
80
82
  resizeWidth.hasSameValue(other.resizeWidth) &&
81
83
  overscan.hasSameValue(other.overscan) &&
82
84
  loadingStrategy.hasSameValue(other.loadingStrategy) &&
@@ -99,6 +101,7 @@ namespace margelo::nitro::onekeyimage::views {
99
101
  autoplay.isProvided() ||
100
102
  recyclingKey.isProvided() ||
101
103
  optimizeTos.isProvided() ||
104
+ round.isProvided() ||
102
105
  resizeWidth.isProvided() ||
103
106
  overscan.isProvided() ||
104
107
  loadingStrategy.isProvided() ||
@@ -12,6 +12,7 @@
12
12
  "autoplay": true,
13
13
  "recyclingKey": true,
14
14
  "optimizeTos": true,
15
+ "round": true,
15
16
  "resizeWidth": true,
16
17
  "overscan": true,
17
18
  "loadingStrategy": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-image",
3
- "version": "3.0.153",
3
+ "version": "3.0.156",
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.153",
84
+ "@onekeyfe/react-native-skeleton": "3.0.156",
85
85
  "react": "*",
86
86
  "react-native": "*",
87
87
  "react-native-nitro-modules": "0.37.0"
@@ -43,6 +43,8 @@ export interface OneKeyImageNativeProps extends HybridViewProps {
43
43
  autoplay?: boolean;
44
44
  recyclingKey?: string;
45
45
  optimizeTos?: boolean;
46
+ /** Clips the native image to an oval using its current bounds. */
47
+ round?: boolean;
46
48
  /** Display width hint in layout units. Native applies the screen density. */
47
49
  resizeWidth?: number;
48
50
  overscan?: number;
package/src/index.tsx CHANGED
@@ -153,6 +153,7 @@ export function OneKeyImage({
153
153
  autoplay,
154
154
  recyclingKey,
155
155
  optimizeTos = true,
156
+ round = false,
156
157
  resizeWidth,
157
158
  overscan = 1.1,
158
159
  loadingStrategy = OneKeyImageLoadingStrategy.STATIC,
@@ -370,6 +371,7 @@ export function OneKeyImage({
370
371
  autoplay: autoplay ?? Platform.OS !== 'android',
371
372
  recyclingKey,
372
373
  optimizeTos,
374
+ round,
373
375
  resizeWidth,
374
376
  overscan,
375
377
  loadingStrategy: