@onekeyfe/react-native-image 3.0.121 → 3.0.123

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.
@@ -344,11 +344,14 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
344
344
  manager: safetyHandle.manager,
345
345
  url: url
346
346
  )
347
- hostView.sd_setImage(
347
+ hostView.sd_internalSetImage(
348
348
  with: url,
349
349
  placeholderImage: nil,
350
350
  options: OneKeyImageRequestContext.renderOptions,
351
351
  context: context,
352
+ setImageBlock: { [weak self] image, _, _, _ in
353
+ self?.applyDisplayedImage(image, generation: generation)
354
+ },
352
355
  progress: { [weak self] receivedSize, _, _ in
353
356
  guard safetyHandle.tracker.inspectReceivedByteCount(Int64(receivedSize)) else { return }
354
357
  DispatchQueue.main.async { [weak self] in
@@ -356,7 +359,9 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
356
359
  self.hostView.sd_cancelCurrentImageLoad()
357
360
  }
358
361
  },
359
- completed: { [weak self] image, error, cacheType, _ in
362
+ completed: { [weak self] image, _, error, cacheType, finished, _ in
363
+ // Progressive loads deliver partial images before the terminal callback.
364
+ guard finished else { return }
360
365
  guard let self, self.requestGeneration == generation else {
361
366
  safetyHandle.finish()
362
367
  return
@@ -515,6 +520,18 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
515
520
  }
516
521
  }
517
522
 
523
+ // OneKey patch: SDWebImage assigns `image` from inside its own completion, which
524
+ // runs before this object's generation guard and never re-checks whether the view
525
+ // still belongs to the request that started the load. Fabric recycles a single
526
+ // OneKeyImage UIView across unrelated images, so a superseded completion could
527
+ // repaint a slot that now shows a different image. Every write goes through here.
528
+ func applyDisplayedImage(_ image: UIImage?, generation: UInt64) {
529
+ guard Self.isCurrentRequestGeneration(generation, current: requestGeneration) else {
530
+ return
531
+ }
532
+ hostView.image = image
533
+ }
534
+
518
535
  private func showLoading(
519
536
  requestIsActive: Bool,
520
537
  letLibraryStartIndicator: Bool
@@ -579,7 +596,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
579
596
  skeletonIndicator.stopAnimatingIndicator()
580
597
  fallbackLayer.isHidden = true
581
598
  resetImageTransition()
582
- hostView.image = image
599
+ applyDisplayedImage(image, generation: generation)
583
600
  hostView.backgroundColor = .clear
584
601
  if requestIsActive {
585
602
  applyLoadedImageTransition(cacheType: .memory)
@@ -1,6 +1,7 @@
1
1
  import SDWebImage
2
2
  import SDWebImageSVGCoder
3
3
  import SDWebImageWebPCoder
4
+ import UIKit
4
5
  import XCTest
5
6
 
6
7
  @testable import OneKeyImage
@@ -543,6 +544,18 @@ final class OneKeyImageInfrastructureTests: XCTestCase {
543
544
  )
544
545
  }
545
546
 
547
+ func testSupersededRequestNeverPaintsRecycledView() throws {
548
+ let image = HybridOneKeyImage()
549
+ let imageView = try XCTUnwrap(image.view as? SDAnimatedImageView)
550
+ let painted = UIImage()
551
+
552
+ image.applyDisplayedImage(painted, generation: .max)
553
+ XCTAssertNil(imageView.image)
554
+
555
+ image.applyDisplayedImage(painted, generation: 0)
556
+ XCTAssertIdentical(imageView.image, painted)
557
+ }
558
+
546
559
  func testAnimatedViewUsesBoundedFrameBuffer() throws {
547
560
  let image = HybridOneKeyImage()
548
561
  let imageView = try XCTUnwrap(image.view as? SDAnimatedImageView)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-image",
3
- "version": "3.0.121",
3
+ "version": "3.0.123",
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.121",
84
+ "@onekeyfe/react-native-skeleton": "3.0.123",
85
85
  "react": "*",
86
86
  "react-native": "*",
87
87
  "react-native-nitro-modules": "0.37.0"