@onekeyfe/react-native-image 3.0.156 → 3.0.157
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 +12 -0
- package/ios/OneKeyImage.swift +83 -14
- package/ios/OneKeyImageRequestContext.swift +38 -0
- package/ios/tests/OneKeyImageInfrastructureTests.swift +85 -0
- package/lib/module/index.js +3 -1
- 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 +6 -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 +6 -0
- package/src/index.tsx +3 -1
|
@@ -180,6 +180,7 @@ internal fun oneKeyImageRequestSignature(
|
|
|
180
180
|
height: Int,
|
|
181
181
|
density: Float,
|
|
182
182
|
resizeWidth: Double? = null,
|
|
183
|
+
resizeHeight: Double? = null,
|
|
183
184
|
): String = listOf(
|
|
184
185
|
rawUrl,
|
|
185
186
|
sourceHeadersJson.orEmpty(),
|
|
@@ -190,6 +191,7 @@ internal fun oneKeyImageRequestSignature(
|
|
|
190
191
|
overscan.toString(),
|
|
191
192
|
round.toString(),
|
|
192
193
|
resizeWidth.toString(),
|
|
194
|
+
resizeHeight.toString(),
|
|
193
195
|
width.toString(),
|
|
194
196
|
height.toString(),
|
|
195
197
|
density.toString(),
|
|
@@ -304,6 +306,14 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
304
306
|
field = value
|
|
305
307
|
requestIdentityChanged()
|
|
306
308
|
}
|
|
309
|
+
// Layout hint pair with resizeWidth; only the iOS pre-layout memory probe
|
|
310
|
+
// consumes it today, Android keys the request on the measured view size.
|
|
311
|
+
override var resizeHeight: Double? = null
|
|
312
|
+
set(value) {
|
|
313
|
+
if (field == value) return
|
|
314
|
+
field = value
|
|
315
|
+
requestIdentityChanged()
|
|
316
|
+
}
|
|
307
317
|
override var loadingStrategy: OneKeyImageLoadingStrategy? = OneKeyImageLoadingStrategy.STATIC
|
|
308
318
|
set(value) {
|
|
309
319
|
field = value
|
|
@@ -403,6 +413,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
403
413
|
optimizeTos = true
|
|
404
414
|
round = false
|
|
405
415
|
resizeWidth = null
|
|
416
|
+
resizeHeight = null
|
|
406
417
|
overscan = 1.1
|
|
407
418
|
loadingStrategy = OneKeyImageLoadingStrategy.STATIC
|
|
408
419
|
placeholderColor = null
|
|
@@ -477,6 +488,7 @@ class HybridOneKeyImage(private val context: ThemedReactContext) :
|
|
|
477
488
|
height = hostView.height,
|
|
478
489
|
density = hostView.resources.displayMetrics.density,
|
|
479
490
|
resizeWidth = resizeWidth,
|
|
491
|
+
resizeHeight = resizeHeight,
|
|
480
492
|
)
|
|
481
493
|
if (!force && signature == lastSignature) return
|
|
482
494
|
lastSignature = signature
|
package/ios/OneKeyImage.swift
CHANGED
|
@@ -150,6 +150,11 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
150
150
|
if !Self.equalOptionalDouble(resizeWidth, oldValue) { identityDidChange() }
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
+
var resizeHeight: Double? {
|
|
154
|
+
didSet {
|
|
155
|
+
if !Self.equalOptionalDouble(resizeHeight, oldValue) { identityDidChange() }
|
|
156
|
+
}
|
|
157
|
+
}
|
|
153
158
|
var overscan: Double? = 1.1 {
|
|
154
159
|
didSet {
|
|
155
160
|
if !Self.equalOptionalDouble(overscan, oldValue) { identityDidChange() }
|
|
@@ -260,7 +265,14 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
260
265
|
guard !hostView.bounds.isEmpty else {
|
|
261
266
|
cancelCurrentRequest(invalidateGeneration: true)
|
|
262
267
|
lastRequestSignature = nil
|
|
263
|
-
|
|
268
|
+
// A memory-cached image shown from `identityDidChange` before layout
|
|
269
|
+
// stays up; layout re-runs this load with real bounds and confirms it.
|
|
270
|
+
if !Self.shouldPreserveDisplayedImage(
|
|
271
|
+
isShowingImage: displayState == .image,
|
|
272
|
+
hasImage: hostView.image != nil
|
|
273
|
+
) {
|
|
274
|
+
showLoading(requestIsActive: false, letLibraryStartIndicator: false)
|
|
275
|
+
}
|
|
264
276
|
return
|
|
265
277
|
}
|
|
266
278
|
guard let rawString = sourceUri, !rawString.isEmpty else {
|
|
@@ -280,6 +292,7 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
280
292
|
contentFit?.stringValue ?? "cover",
|
|
281
293
|
String(optimizeTos ?? true),
|
|
282
294
|
resizeWidth.map(String.init(describing:)) ?? "",
|
|
295
|
+
resizeHeight.map(String.init(describing:)) ?? "",
|
|
283
296
|
String(overscan ?? 1.1),
|
|
284
297
|
String(Int(hostView.bounds.width.rounded())),
|
|
285
298
|
String(Int(hostView.bounds.height.rounded())),
|
|
@@ -295,7 +308,20 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
295
308
|
onLoadStart?()
|
|
296
309
|
guard Self.isCurrentRequestGeneration(generation, current: requestGeneration) else { return }
|
|
297
310
|
if showMemoryCachedImageIfAvailable(requestIsActive: true) { return }
|
|
298
|
-
|
|
311
|
+
// The pre-layout probe may have shown this identity from another thumbnail
|
|
312
|
+
// key (a preload's, or an earlier layout size). Keep it on screen as the
|
|
313
|
+
// placeholder while the exact rendition loads: blanking to a skeleton and
|
|
314
|
+
// redrawing is worse than the skeleton it replaced.
|
|
315
|
+
let preservedImage =
|
|
316
|
+
Self.shouldPreserveDisplayedImage(
|
|
317
|
+
isShowingImage: displayState == .image,
|
|
318
|
+
hasImage: hostView.image != nil
|
|
319
|
+
) ? hostView.image : nil
|
|
320
|
+
showLoading(
|
|
321
|
+
requestIsActive: true,
|
|
322
|
+
letLibraryStartIndicator: true,
|
|
323
|
+
preservedImage: preservedImage
|
|
324
|
+
)
|
|
299
325
|
|
|
300
326
|
if let violation = OneKeyImageSafetyPolicy.preflight(source: rawString) {
|
|
301
327
|
finishWithError(violation, generation: generation)
|
|
@@ -327,7 +353,8 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
327
353
|
url: requestURL,
|
|
328
354
|
rawURL: rawURL,
|
|
329
355
|
generation: generation,
|
|
330
|
-
mayFallbackToRaw: requestURL != rawURL
|
|
356
|
+
mayFallbackToRaw: requestURL != rawURL,
|
|
357
|
+
placeholderImage: preservedImage
|
|
331
358
|
)
|
|
332
359
|
}
|
|
333
360
|
|
|
@@ -335,7 +362,8 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
335
362
|
url: URL,
|
|
336
363
|
rawURL: URL,
|
|
337
364
|
generation: UInt64,
|
|
338
|
-
mayFallbackToRaw: Bool
|
|
365
|
+
mayFallbackToRaw: Bool,
|
|
366
|
+
placeholderImage: UIImage? = nil
|
|
339
367
|
) {
|
|
340
368
|
guard Self.isCurrentRequestGeneration(generation, current: requestGeneration) else { return }
|
|
341
369
|
let rawScreenScale: CGFloat = hostView.window?.screen.scale ?? UIScreen.main.scale
|
|
@@ -363,7 +391,9 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
363
391
|
)
|
|
364
392
|
hostView.sd_internalSetImage(
|
|
365
393
|
with: url,
|
|
366
|
-
|
|
394
|
+
// SDWebImage resets the image view when it starts a load; hand it the
|
|
395
|
+
// preserved image so the view keeps showing it until the load lands.
|
|
396
|
+
placeholderImage: placeholderImage,
|
|
367
397
|
options: OneKeyImageRequestContext.renderOptions,
|
|
368
398
|
context: context,
|
|
369
399
|
setImageBlock: { [weak self] image, _, _, _ in
|
|
@@ -552,18 +582,40 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
552
582
|
|
|
553
583
|
private func showLoading(
|
|
554
584
|
requestIsActive: Bool,
|
|
555
|
-
letLibraryStartIndicator: Bool
|
|
585
|
+
letLibraryStartIndicator: Bool,
|
|
586
|
+
preservedImage: UIImage? = nil
|
|
556
587
|
) {
|
|
557
588
|
displayState = .loading
|
|
558
589
|
requestActive = requestIsActive
|
|
559
590
|
resetImageTransition()
|
|
560
|
-
hostView.image = nil
|
|
561
591
|
fallbackLayer.isHidden = true
|
|
592
|
+
if let preservedImage {
|
|
593
|
+
// Same identity, different thumbnail key: the image already on screen
|
|
594
|
+
// stands in for the placeholder, so no blank frame and no indicator.
|
|
595
|
+
hostView.image = preservedImage
|
|
596
|
+
skeletonIndicator.stopAnimatingIndicator()
|
|
597
|
+
hostView.backgroundColor = .clear
|
|
598
|
+
return
|
|
599
|
+
}
|
|
600
|
+
hostView.image = nil
|
|
562
601
|
applyLoadingAppearance(letLibraryStartIndicator: letLibraryStartIndicator)
|
|
563
602
|
}
|
|
564
603
|
|
|
604
|
+
/// Whether the image currently on screen should stay up while a load for the
|
|
605
|
+
/// SAME identity runs (bounds not laid out yet, or the laid-out request key
|
|
606
|
+
/// differs from the one the pre-layout probe hit). Pure for testability.
|
|
607
|
+
static func shouldPreserveDisplayedImage(isShowingImage: Bool, hasImage: Bool) -> Bool {
|
|
608
|
+
isShowingImage && hasImage
|
|
609
|
+
}
|
|
610
|
+
|
|
565
611
|
private func showMemoryCachedImageIfAvailable(requestIsActive: Bool) -> Bool {
|
|
566
|
-
|
|
612
|
+
// JS leaves `cachePolicy` unset for the common case and Fabric then hands
|
|
613
|
+
// Nitro a nil, which the request path already treats as memory-disk; the
|
|
614
|
+
// probe must agree, otherwise a nil policy skips the memory lookup entirely
|
|
615
|
+
// and every mount pays the async pipeline round trip (an icon skeleton
|
|
616
|
+
// frame) for an image that is already decoded in memory.
|
|
617
|
+
let effectivePolicy = cachePolicy ?? .memoryDisk
|
|
618
|
+
guard effectivePolicy == .memory || effectivePolicy == .memoryDisk,
|
|
567
619
|
let sourceUri,
|
|
568
620
|
let rawURL = URL(string: sourceUri) else {
|
|
569
621
|
return false
|
|
@@ -583,12 +635,21 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
583
635
|
hasCustomIdentity: hasCustomIdentity
|
|
584
636
|
)
|
|
585
637
|
: rawURL
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
638
|
+
// The thumbnail size is part of the cache key. Laid out, it is this view's
|
|
639
|
+
// own request key; before layout it comes from the resize hints, under
|
|
640
|
+
// this view's contentFit and under `.cover` (a preload's key). With no
|
|
641
|
+
// bounds and no hint the un-thumbnailed key is the only thing to try.
|
|
642
|
+
let thumbnailCandidates: [CGSize?] = {
|
|
643
|
+
let sizes = OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
644
|
+
bounds: hostView.bounds.size,
|
|
645
|
+
resizeWidth: resizeWidth,
|
|
646
|
+
resizeHeight: resizeHeight,
|
|
647
|
+
scale: screenScale,
|
|
648
|
+
contentFit: contentFit ?? .cover
|
|
649
|
+
)
|
|
650
|
+
return sizes.isEmpty ? [nil] : sizes
|
|
651
|
+
}()
|
|
652
|
+
func memoryCachedImage(for url: URL, thumbnailPixelSize: CGSize?) -> UIImage? {
|
|
592
653
|
let context = OneKeyImageRequestContext.make(
|
|
593
654
|
headersJson: sourceHeadersJson,
|
|
594
655
|
cachePolicy: cachePolicy ?? .memoryDisk,
|
|
@@ -603,6 +664,14 @@ final class HybridOneKeyImage: HybridOneKeyImageSpec, RecyclableView {
|
|
|
603
664
|
}
|
|
604
665
|
return cache.imageFromMemoryCache(forKey: key)
|
|
605
666
|
}
|
|
667
|
+
func memoryCachedImage(for url: URL) -> UIImage? {
|
|
668
|
+
for thumbnailPixelSize in thumbnailCandidates {
|
|
669
|
+
if let image = memoryCachedImage(for: url, thumbnailPixelSize: thumbnailPixelSize) {
|
|
670
|
+
return image
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return nil
|
|
674
|
+
}
|
|
606
675
|
guard let image = memoryCachedImage(for: requestURL)
|
|
607
676
|
?? (requestURL == rawURL ? nil : memoryCachedImage(for: rawURL)) else {
|
|
608
677
|
return false
|
|
@@ -610,6 +610,44 @@ enum OneKeyImageDecodeSizing {
|
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
612
|
|
|
613
|
+
/// Decode-thumbnail sizes worth probing the memory cache with, most specific
|
|
614
|
+
/// first. The thumbnail size is part of the SDWebImage cache key, so a probe
|
|
615
|
+
/// only hits when it reproduces the key some earlier load stored under.
|
|
616
|
+
///
|
|
617
|
+
/// - Laid out: exactly the size this view's own request uses (`bounds` +
|
|
618
|
+
/// `contentFit`), nothing else.
|
|
619
|
+
/// - Before layout the bounds are empty, but the JS side already knows the
|
|
620
|
+
/// display size through the `resizeWidth` / `resizeHeight` hints (the same
|
|
621
|
+
/// fields a preload takes). Two keys can hold the image then: the one the
|
|
622
|
+
/// laid-out request will ask for (hint + this view's `contentFit`) and the
|
|
623
|
+
/// one a preload stored (hint + `.cover`, see `HybridOneKeyImageCache`).
|
|
624
|
+
/// They coincide for a square hint or `.cover`; otherwise both are probed.
|
|
625
|
+
/// - No bounds and no usable hint: nothing to probe with.
|
|
626
|
+
static func probeThumbnailPixelSizes(
|
|
627
|
+
bounds: CGSize,
|
|
628
|
+
resizeWidth: Double?,
|
|
629
|
+
resizeHeight: Double?,
|
|
630
|
+
scale: CGFloat,
|
|
631
|
+
contentFit: OneKeyImageContentFit
|
|
632
|
+
) -> [CGSize] {
|
|
633
|
+
if bounds.width.isFinite, bounds.height.isFinite, bounds.width > 0, bounds.height > 0 {
|
|
634
|
+
return thumbnailPixelSize(viewSize: bounds, scale: scale, contentFit: contentFit)
|
|
635
|
+
.map { [$0] } ?? []
|
|
636
|
+
}
|
|
637
|
+
guard let hint = logicalViewSize(width: resizeWidth, height: resizeHeight) else {
|
|
638
|
+
return []
|
|
639
|
+
}
|
|
640
|
+
var sizes: [CGSize] = []
|
|
641
|
+
for fit in [contentFit, .cover] {
|
|
642
|
+
if let size = thumbnailPixelSize(viewSize: hint, scale: scale, contentFit: fit),
|
|
643
|
+
!sizes.contains(size)
|
|
644
|
+
{
|
|
645
|
+
sizes.append(size)
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
return sizes
|
|
649
|
+
}
|
|
650
|
+
|
|
613
651
|
static func thumbnailPixelSize(
|
|
614
652
|
viewSize: CGSize,
|
|
615
653
|
scale: CGFloat,
|
|
@@ -310,6 +310,91 @@ final class OneKeyImageInfrastructureTests: XCTestCase {
|
|
|
310
310
|
)
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
+
// The pre-layout memory probe is only useful if it reproduces a key some
|
|
314
|
+
// earlier load stored under. These pin the probe against the two real key
|
|
315
|
+
// producers: the laid-out render request (bounds + contentFit) and the
|
|
316
|
+
// preload (logicalViewSize(resizeWidth, resizeHeight) + .cover).
|
|
317
|
+
private func renderKey(bounds: CGSize, fit: OneKeyImageContentFit) throws -> CGSize {
|
|
318
|
+
try XCTUnwrap(
|
|
319
|
+
OneKeyImageDecodeSizing.thumbnailPixelSize(viewSize: bounds, scale: 3, contentFit: fit)
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private func preloadKey(width: Double?, height: Double?) throws -> CGSize {
|
|
324
|
+
try renderKey(
|
|
325
|
+
bounds: try XCTUnwrap(OneKeyImageDecodeSizing.logicalViewSize(width: width, height: height)),
|
|
326
|
+
fit: .cover
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
func testLaidOutProbeUsesExactlyTheRenderRequestKey() throws {
|
|
331
|
+
let bounds = CGSize(width: 40, height: 64)
|
|
332
|
+
for fit in [OneKeyImageContentFit.cover, .contain, .fill, .center] {
|
|
333
|
+
XCTAssertEqual(
|
|
334
|
+
OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
335
|
+
bounds: bounds, resizeWidth: 32, resizeHeight: 48, scale: 3, contentFit: fit
|
|
336
|
+
),
|
|
337
|
+
[try renderKey(bounds: bounds, fit: fit)],
|
|
338
|
+
"\(fit)"
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
func testPreLayoutSquareHintMatchesPreloadAndRenderKeys() throws {
|
|
344
|
+
// A token icon: resizeWidth only, laid out square, cover. One key, shared
|
|
345
|
+
// by the preload, the laid-out request and the probe.
|
|
346
|
+
let sizes = OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
347
|
+
bounds: .zero, resizeWidth: 40, resizeHeight: nil, scale: 3, contentFit: .cover
|
|
348
|
+
)
|
|
349
|
+
XCTAssertEqual(sizes, [CGSize(width: 120, height: 120)])
|
|
350
|
+
XCTAssertEqual(sizes, [try preloadKey(width: 40, height: nil)])
|
|
351
|
+
XCTAssertEqual(sizes, [try renderKey(bounds: CGSize(width: 40, height: 40), fit: .cover)])
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
func testPreLayoutRectangularHintProbesRenderAndPreloadKeys() throws {
|
|
355
|
+
// The README preload shape (48x64 @3) under a non-cover view: the laid-out
|
|
356
|
+
// request key comes first, the preload's cover key second, no duplicates.
|
|
357
|
+
let sizes = OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
358
|
+
bounds: .zero, resizeWidth: 48, resizeHeight: 64, scale: 3, contentFit: .contain
|
|
359
|
+
)
|
|
360
|
+
XCTAssertEqual(
|
|
361
|
+
sizes,
|
|
362
|
+
[
|
|
363
|
+
try renderKey(bounds: CGSize(width: 48, height: 64), fit: .contain),
|
|
364
|
+
try preloadKey(width: 48, height: 64),
|
|
365
|
+
]
|
|
366
|
+
)
|
|
367
|
+
XCTAssertEqual(sizes, [CGSize(width: 144, height: 192), CGSize(width: 192, height: 192)])
|
|
368
|
+
// Under cover both collapse to the preload key.
|
|
369
|
+
XCTAssertEqual(
|
|
370
|
+
OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
371
|
+
bounds: .zero, resizeWidth: 48, resizeHeight: 64, scale: 3, contentFit: .cover
|
|
372
|
+
),
|
|
373
|
+
[try preloadKey(width: 48, height: 64)]
|
|
374
|
+
)
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
func testPreLayoutProbeWithoutHintHasNothingToTry() {
|
|
378
|
+
XCTAssertEqual(
|
|
379
|
+
OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
380
|
+
bounds: .zero, resizeWidth: nil, resizeHeight: nil, scale: 3, contentFit: .cover
|
|
381
|
+
),
|
|
382
|
+
[]
|
|
383
|
+
)
|
|
384
|
+
XCTAssertEqual(
|
|
385
|
+
OneKeyImageDecodeSizing.probeThumbnailPixelSizes(
|
|
386
|
+
bounds: .zero, resizeWidth: 0, resizeHeight: -1, scale: 3, contentFit: .cover
|
|
387
|
+
),
|
|
388
|
+
[]
|
|
389
|
+
)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
func testDisplayedImageIsPreservedOnlyWhileShowingOne() {
|
|
393
|
+
XCTAssertTrue(HybridOneKeyImage.shouldPreserveDisplayedImage(isShowingImage: true, hasImage: true))
|
|
394
|
+
XCTAssertFalse(HybridOneKeyImage.shouldPreserveDisplayedImage(isShowingImage: true, hasImage: false))
|
|
395
|
+
XCTAssertFalse(HybridOneKeyImage.shouldPreserveDisplayedImage(isShowingImage: false, hasImage: true))
|
|
396
|
+
}
|
|
397
|
+
|
|
313
398
|
func testNoSizePreloadUsesCappedDecodeTarget() {
|
|
314
399
|
XCTAssertEqual(HybridOneKeyImageCache.maximumConcurrentPreloads, 4)
|
|
315
400
|
XCTAssertEqual(
|
package/lib/module/index.js
CHANGED
|
@@ -46,6 +46,7 @@ export function OneKeyImage({
|
|
|
46
46
|
optimizeTos = true,
|
|
47
47
|
round = false,
|
|
48
48
|
resizeWidth,
|
|
49
|
+
resizeHeight,
|
|
49
50
|
overscan = 1.1,
|
|
50
51
|
loadingStrategy = OneKeyImageLoadingStrategy.STATIC,
|
|
51
52
|
placeholderColor,
|
|
@@ -60,7 +61,7 @@ export function OneKeyImage({
|
|
|
60
61
|
}) {
|
|
61
62
|
const normalized = useMemo(() => normalizeSource(source), [source]);
|
|
62
63
|
const resolvedCachePolicy = cachePolicy ?? normalized?.cachePolicy ?? OneKeyImageCachePolicy.MEMORY_DISK;
|
|
63
|
-
const identity = `${normalized?.uri ?? ''}|${JSON.stringify(normalized?.headers ?? {})}|${resolvedCachePolicy}|${recyclingKey ?? ''}|${contentFit}|${optimizeTos ? '1' : '0'}|${resizeWidth ?? ''}|${overscan}`;
|
|
64
|
+
const identity = `${normalized?.uri ?? ''}|${JSON.stringify(normalized?.headers ?? {})}|${resolvedCachePolicy}|${recyclingKey ?? ''}|${contentFit}|${optimizeTos ? '1' : '0'}|${resizeWidth ?? ''}|${resizeHeight ?? ''}|${overscan}`;
|
|
64
65
|
const hasSource = normalized != null;
|
|
65
66
|
const hasOverlay = placeholder != null || fallback != null;
|
|
66
67
|
const [loadState, setLoadState] = useState({
|
|
@@ -215,6 +216,7 @@ export function OneKeyImage({
|
|
|
215
216
|
optimizeTos,
|
|
216
217
|
round,
|
|
217
218
|
resizeWidth,
|
|
219
|
+
resizeHeight,
|
|
218
220
|
overscan,
|
|
219
221
|
loadingStrategy: placeholder == null ? loadingStrategy : OneKeyImageLoadingStrategy.NONE,
|
|
220
222
|
placeholderColor
|
|
@@ -156,6 +156,15 @@ namespace margelo::nitro::onekeyimage {
|
|
|
156
156
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JDouble> /* resizeWidth */)>("setResizeWidth");
|
|
157
157
|
method(_javaPart, resizeWidth.has_value() ? jni::JDouble::valueOf(resizeWidth.value()) : nullptr);
|
|
158
158
|
}
|
|
159
|
+
std::optional<double> JHybridOneKeyImageSpec::getResizeHeight() {
|
|
160
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getResizeHeight");
|
|
161
|
+
auto __result = method(_javaPart);
|
|
162
|
+
return __result != nullptr ? std::make_optional(__result->value()) : std::nullopt;
|
|
163
|
+
}
|
|
164
|
+
void JHybridOneKeyImageSpec::setResizeHeight(std::optional<double> resizeHeight) {
|
|
165
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JDouble> /* resizeHeight */)>("setResizeHeight");
|
|
166
|
+
method(_javaPart, resizeHeight.has_value() ? jni::JDouble::valueOf(resizeHeight.value()) : nullptr);
|
|
167
|
+
}
|
|
159
168
|
std::optional<double> JHybridOneKeyImageSpec::getOverscan() {
|
|
160
169
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getOverscan");
|
|
161
170
|
auto __result = method(_javaPart);
|
|
@@ -70,6 +70,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
70
70
|
void setRound(std::optional<bool> round) override;
|
|
71
71
|
std::optional<double> getResizeWidth() override;
|
|
72
72
|
void setResizeWidth(std::optional<double> resizeWidth) override;
|
|
73
|
+
std::optional<double> getResizeHeight() override;
|
|
74
|
+
void setResizeHeight(std::optional<double> resizeHeight) override;
|
|
73
75
|
std::optional<double> getOverscan() override;
|
|
74
76
|
void setOverscan(std::optional<double> overscan) override;
|
|
75
77
|
std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() override;
|
|
@@ -103,6 +103,11 @@ void JHybridOneKeyImageStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
|
|
|
103
103
|
: !newProps->resizeWidth.hasSameValue(oldProps->resizeWidth)) {
|
|
104
104
|
hybridView->setResizeWidth(newProps->resizeWidth.get());
|
|
105
105
|
}
|
|
106
|
+
if (oldProps == nullptr
|
|
107
|
+
? newProps->resizeHeight.isProvided()
|
|
108
|
+
: !newProps->resizeHeight.hasSameValue(oldProps->resizeHeight)) {
|
|
109
|
+
hybridView->setResizeHeight(newProps->resizeHeight.get());
|
|
110
|
+
}
|
|
106
111
|
if (oldProps == nullptr
|
|
107
112
|
? newProps->overscan.isProvided()
|
|
108
113
|
: !newProps->overscan.hasSameValue(oldProps->overscan)) {
|
package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt
CHANGED
|
@@ -87,6 +87,12 @@ abstract class HybridOneKeyImageSpec: HybridView() {
|
|
|
87
87
|
@set:Keep
|
|
88
88
|
abstract var resizeWidth: Double?
|
|
89
89
|
|
|
90
|
+
@get:DoNotStrip
|
|
91
|
+
@get:Keep
|
|
92
|
+
@set:DoNotStrip
|
|
93
|
+
@set:Keep
|
|
94
|
+
abstract var resizeHeight: Double?
|
|
95
|
+
|
|
90
96
|
@get:DoNotStrip
|
|
91
97
|
@get:Keep
|
|
92
98
|
@set:DoNotStrip
|
|
@@ -148,6 +148,13 @@ namespace margelo::nitro::onekeyimage {
|
|
|
148
148
|
inline void setResizeWidth(std::optional<double> resizeWidth) noexcept override {
|
|
149
149
|
_swiftPart.setResizeWidth(resizeWidth);
|
|
150
150
|
}
|
|
151
|
+
inline std::optional<double> getResizeHeight() noexcept override {
|
|
152
|
+
auto __result = _swiftPart.getResizeHeight();
|
|
153
|
+
return __result;
|
|
154
|
+
}
|
|
155
|
+
inline void setResizeHeight(std::optional<double> resizeHeight) noexcept override {
|
|
156
|
+
_swiftPart.setResizeHeight(resizeHeight);
|
|
157
|
+
}
|
|
151
158
|
inline std::optional<double> getOverscan() noexcept override {
|
|
152
159
|
auto __result = _swiftPart.getOverscan();
|
|
153
160
|
return __result;
|
|
@@ -158,6 +158,12 @@ using namespace margelo::nitro::onekeyimage::views;
|
|
|
158
158
|
: !newViewProps.resizeWidth.hasSameValue(oldViewProps->resizeWidth)) {
|
|
159
159
|
swiftPart.setResizeWidth(newViewProps.resizeWidth.get());
|
|
160
160
|
}
|
|
161
|
+
// resizeHeight: optional
|
|
162
|
+
if (oldViewProps == nullptr
|
|
163
|
+
? newViewProps.resizeHeight.isProvided()
|
|
164
|
+
: !newViewProps.resizeHeight.hasSameValue(oldViewProps->resizeHeight)) {
|
|
165
|
+
swiftPart.setResizeHeight(newViewProps.resizeHeight.get());
|
|
166
|
+
}
|
|
161
167
|
// overscan: optional
|
|
162
168
|
if (oldViewProps == nullptr
|
|
163
169
|
? newViewProps.overscan.isProvided()
|
|
@@ -20,6 +20,7 @@ public protocol HybridOneKeyImageSpec_protocol: HybridObject, HybridView {
|
|
|
20
20
|
var optimizeTos: Bool? { get set }
|
|
21
21
|
var round: Bool? { get set }
|
|
22
22
|
var resizeWidth: Double? { get set }
|
|
23
|
+
var resizeHeight: Double? { get set }
|
|
23
24
|
var overscan: Double? { get set }
|
|
24
25
|
var loadingStrategy: OneKeyImageLoadingStrategy? { get set }
|
|
25
26
|
var placeholderColor: String? { get set }
|
|
@@ -340,6 +340,30 @@ open class HybridOneKeyImageSpec_cxx {
|
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
+
public final var resizeHeight: bridge.std__optional_double_ {
|
|
344
|
+
@inline(__always)
|
|
345
|
+
get {
|
|
346
|
+
return { () -> bridge.std__optional_double_ in
|
|
347
|
+
if let __unwrappedValue = self.__implementation.resizeHeight {
|
|
348
|
+
return bridge.create_std__optional_double_(__unwrappedValue)
|
|
349
|
+
} else {
|
|
350
|
+
return .init()
|
|
351
|
+
}
|
|
352
|
+
}()
|
|
353
|
+
}
|
|
354
|
+
@inline(__always)
|
|
355
|
+
set {
|
|
356
|
+
self.__implementation.resizeHeight = { () -> Double? in
|
|
357
|
+
if bridge.has_value_std__optional_double_(newValue) {
|
|
358
|
+
let __unwrapped = bridge.get_std__optional_double_(newValue)
|
|
359
|
+
return __unwrapped
|
|
360
|
+
} else {
|
|
361
|
+
return nil
|
|
362
|
+
}
|
|
363
|
+
}()
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
343
367
|
public final var overscan: bridge.std__optional_double_ {
|
|
344
368
|
@inline(__always)
|
|
345
369
|
get {
|
|
@@ -34,6 +34,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
34
34
|
prototype.registerHybridSetter("round", &HybridOneKeyImageSpec::setRound);
|
|
35
35
|
prototype.registerHybridGetter("resizeWidth", &HybridOneKeyImageSpec::getResizeWidth);
|
|
36
36
|
prototype.registerHybridSetter("resizeWidth", &HybridOneKeyImageSpec::setResizeWidth);
|
|
37
|
+
prototype.registerHybridGetter("resizeHeight", &HybridOneKeyImageSpec::getResizeHeight);
|
|
38
|
+
prototype.registerHybridSetter("resizeHeight", &HybridOneKeyImageSpec::setResizeHeight);
|
|
37
39
|
prototype.registerHybridGetter("overscan", &HybridOneKeyImageSpec::getOverscan);
|
|
38
40
|
prototype.registerHybridSetter("overscan", &HybridOneKeyImageSpec::setOverscan);
|
|
39
41
|
prototype.registerHybridGetter("loadingStrategy", &HybridOneKeyImageSpec::getLoadingStrategy);
|
|
@@ -80,6 +80,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
80
80
|
virtual void setRound(std::optional<bool> round) = 0;
|
|
81
81
|
virtual std::optional<double> getResizeWidth() = 0;
|
|
82
82
|
virtual void setResizeWidth(std::optional<double> resizeWidth) = 0;
|
|
83
|
+
virtual std::optional<double> getResizeHeight() = 0;
|
|
84
|
+
virtual void setResizeHeight(std::optional<double> resizeHeight) = 0;
|
|
83
85
|
virtual std::optional<double> getOverscan() = 0;
|
|
84
86
|
virtual void setOverscan(std::optional<double> overscan) = 0;
|
|
85
87
|
virtual std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() = 0;
|
|
@@ -30,6 +30,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
30
30
|
optimizeTos(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "optimizeTos", rawProps, sourceProps.optimizeTos)),
|
|
31
31
|
round(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "round", rawProps, sourceProps.round)),
|
|
32
32
|
resizeWidth(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeWidth", rawProps, sourceProps.resizeWidth)),
|
|
33
|
+
resizeHeight(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeHeight", rawProps, sourceProps.resizeHeight)),
|
|
33
34
|
overscan(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "overscan", rawProps, sourceProps.overscan)),
|
|
34
35
|
loadingStrategy(nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>>::fromRawValue("OneKeyImage", "loadingStrategy", rawProps, sourceProps.loadingStrategy)),
|
|
35
36
|
placeholderColor(nitro::ReactProp<std::optional<std::string>>::fromRawValue("OneKeyImage", "placeholderColor", rawProps, sourceProps.placeholderColor)),
|
|
@@ -52,6 +53,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
52
53
|
case hashString("optimizeTos"): return true;
|
|
53
54
|
case hashString("round"): return true;
|
|
54
55
|
case hashString("resizeWidth"): return true;
|
|
56
|
+
case hashString("resizeHeight"): return true;
|
|
55
57
|
case hashString("overscan"): return true;
|
|
56
58
|
case hashString("loadingStrategy"): return true;
|
|
57
59
|
case hashString("placeholderColor"): return true;
|
|
@@ -58,6 +58,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
58
58
|
nitro::ReactProp<std::optional<bool>> optimizeTos;
|
|
59
59
|
nitro::ReactProp<std::optional<bool>> round;
|
|
60
60
|
nitro::ReactProp<std::optional<double>> resizeWidth;
|
|
61
|
+
nitro::ReactProp<std::optional<double>> resizeHeight;
|
|
61
62
|
nitro::ReactProp<std::optional<double>> overscan;
|
|
62
63
|
nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>> loadingStrategy;
|
|
63
64
|
nitro::ReactProp<std::optional<std::string>> placeholderColor;
|
|
@@ -80,6 +81,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
80
81
|
optimizeTos.hasSameValue(other.optimizeTos) &&
|
|
81
82
|
round.hasSameValue(other.round) &&
|
|
82
83
|
resizeWidth.hasSameValue(other.resizeWidth) &&
|
|
84
|
+
resizeHeight.hasSameValue(other.resizeHeight) &&
|
|
83
85
|
overscan.hasSameValue(other.overscan) &&
|
|
84
86
|
loadingStrategy.hasSameValue(other.loadingStrategy) &&
|
|
85
87
|
placeholderColor.hasSameValue(other.placeholderColor) &&
|
|
@@ -103,6 +105,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
103
105
|
optimizeTos.isProvided() ||
|
|
104
106
|
round.isProvided() ||
|
|
105
107
|
resizeWidth.isProvided() ||
|
|
108
|
+
resizeHeight.isProvided() ||
|
|
106
109
|
overscan.isProvided() ||
|
|
107
110
|
loadingStrategy.isProvided() ||
|
|
108
111
|
placeholderColor.isProvided() ||
|
|
@@ -36,6 +36,12 @@ export interface OneKeyImageNativeProps extends HybridViewProps {
|
|
|
36
36
|
round?: boolean;
|
|
37
37
|
/** Display width hint in layout units. Native applies the screen density. */
|
|
38
38
|
resizeWidth?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Display height hint in layout units. With `resizeWidth` it lets the
|
|
41
|
+
* pre-layout memory-cache probe derive the same decode thumbnail a preload
|
|
42
|
+
* with the same hints stored; omitted, the hint is a square of `resizeWidth`.
|
|
43
|
+
*/
|
|
44
|
+
resizeHeight?: number;
|
|
39
45
|
overscan?: number;
|
|
40
46
|
loadingStrategy?: OneKeyImageLoadingStrategy;
|
|
41
47
|
/** Theme-aware color used by static loading, error, and fallback states. */
|
|
@@ -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, round, 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, resizeHeight, 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>;
|
|
@@ -156,6 +156,15 @@ namespace margelo::nitro::onekeyimage {
|
|
|
156
156
|
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JDouble> /* resizeWidth */)>("setResizeWidth");
|
|
157
157
|
method(_javaPart, resizeWidth.has_value() ? jni::JDouble::valueOf(resizeWidth.value()) : nullptr);
|
|
158
158
|
}
|
|
159
|
+
std::optional<double> JHybridOneKeyImageSpec::getResizeHeight() {
|
|
160
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getResizeHeight");
|
|
161
|
+
auto __result = method(_javaPart);
|
|
162
|
+
return __result != nullptr ? std::make_optional(__result->value()) : std::nullopt;
|
|
163
|
+
}
|
|
164
|
+
void JHybridOneKeyImageSpec::setResizeHeight(std::optional<double> resizeHeight) {
|
|
165
|
+
static const auto method = _javaPart->javaClassStatic()->getMethod<void(jni::alias_ref<jni::JDouble> /* resizeHeight */)>("setResizeHeight");
|
|
166
|
+
method(_javaPart, resizeHeight.has_value() ? jni::JDouble::valueOf(resizeHeight.value()) : nullptr);
|
|
167
|
+
}
|
|
159
168
|
std::optional<double> JHybridOneKeyImageSpec::getOverscan() {
|
|
160
169
|
static const auto method = _javaPart->javaClassStatic()->getMethod<jni::local_ref<jni::JDouble>()>("getOverscan");
|
|
161
170
|
auto __result = method(_javaPart);
|
|
@@ -70,6 +70,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
70
70
|
void setRound(std::optional<bool> round) override;
|
|
71
71
|
std::optional<double> getResizeWidth() override;
|
|
72
72
|
void setResizeWidth(std::optional<double> resizeWidth) override;
|
|
73
|
+
std::optional<double> getResizeHeight() override;
|
|
74
|
+
void setResizeHeight(std::optional<double> resizeHeight) override;
|
|
73
75
|
std::optional<double> getOverscan() override;
|
|
74
76
|
void setOverscan(std::optional<double> overscan) override;
|
|
75
77
|
std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() override;
|
|
@@ -103,6 +103,11 @@ void JHybridOneKeyImageStateUpdater::updateViewProps(jni::alias_ref<jni::JClass>
|
|
|
103
103
|
: !newProps->resizeWidth.hasSameValue(oldProps->resizeWidth)) {
|
|
104
104
|
hybridView->setResizeWidth(newProps->resizeWidth.get());
|
|
105
105
|
}
|
|
106
|
+
if (oldProps == nullptr
|
|
107
|
+
? newProps->resizeHeight.isProvided()
|
|
108
|
+
: !newProps->resizeHeight.hasSameValue(oldProps->resizeHeight)) {
|
|
109
|
+
hybridView->setResizeHeight(newProps->resizeHeight.get());
|
|
110
|
+
}
|
|
106
111
|
if (oldProps == nullptr
|
|
107
112
|
? newProps->overscan.isProvided()
|
|
108
113
|
: !newProps->overscan.hasSameValue(oldProps->overscan)) {
|
package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyImageSpec.kt
CHANGED
|
@@ -87,6 +87,12 @@ abstract class HybridOneKeyImageSpec: HybridView() {
|
|
|
87
87
|
@set:Keep
|
|
88
88
|
abstract var resizeWidth: Double?
|
|
89
89
|
|
|
90
|
+
@get:DoNotStrip
|
|
91
|
+
@get:Keep
|
|
92
|
+
@set:DoNotStrip
|
|
93
|
+
@set:Keep
|
|
94
|
+
abstract var resizeHeight: Double?
|
|
95
|
+
|
|
90
96
|
@get:DoNotStrip
|
|
91
97
|
@get:Keep
|
|
92
98
|
@set:DoNotStrip
|
|
@@ -148,6 +148,13 @@ namespace margelo::nitro::onekeyimage {
|
|
|
148
148
|
inline void setResizeWidth(std::optional<double> resizeWidth) noexcept override {
|
|
149
149
|
_swiftPart.setResizeWidth(resizeWidth);
|
|
150
150
|
}
|
|
151
|
+
inline std::optional<double> getResizeHeight() noexcept override {
|
|
152
|
+
auto __result = _swiftPart.getResizeHeight();
|
|
153
|
+
return __result;
|
|
154
|
+
}
|
|
155
|
+
inline void setResizeHeight(std::optional<double> resizeHeight) noexcept override {
|
|
156
|
+
_swiftPart.setResizeHeight(resizeHeight);
|
|
157
|
+
}
|
|
151
158
|
inline std::optional<double> getOverscan() noexcept override {
|
|
152
159
|
auto __result = _swiftPart.getOverscan();
|
|
153
160
|
return __result;
|
|
@@ -158,6 +158,12 @@ using namespace margelo::nitro::onekeyimage::views;
|
|
|
158
158
|
: !newViewProps.resizeWidth.hasSameValue(oldViewProps->resizeWidth)) {
|
|
159
159
|
swiftPart.setResizeWidth(newViewProps.resizeWidth.get());
|
|
160
160
|
}
|
|
161
|
+
// resizeHeight: optional
|
|
162
|
+
if (oldViewProps == nullptr
|
|
163
|
+
? newViewProps.resizeHeight.isProvided()
|
|
164
|
+
: !newViewProps.resizeHeight.hasSameValue(oldViewProps->resizeHeight)) {
|
|
165
|
+
swiftPart.setResizeHeight(newViewProps.resizeHeight.get());
|
|
166
|
+
}
|
|
161
167
|
// overscan: optional
|
|
162
168
|
if (oldViewProps == nullptr
|
|
163
169
|
? newViewProps.overscan.isProvided()
|
|
@@ -20,6 +20,7 @@ public protocol HybridOneKeyImageSpec_protocol: HybridObject, HybridView {
|
|
|
20
20
|
var optimizeTos: Bool? { get set }
|
|
21
21
|
var round: Bool? { get set }
|
|
22
22
|
var resizeWidth: Double? { get set }
|
|
23
|
+
var resizeHeight: Double? { get set }
|
|
23
24
|
var overscan: Double? { get set }
|
|
24
25
|
var loadingStrategy: OneKeyImageLoadingStrategy? { get set }
|
|
25
26
|
var placeholderColor: String? { get set }
|
|
@@ -340,6 +340,30 @@ open class HybridOneKeyImageSpec_cxx {
|
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
+
public final var resizeHeight: bridge.std__optional_double_ {
|
|
344
|
+
@inline(__always)
|
|
345
|
+
get {
|
|
346
|
+
return { () -> bridge.std__optional_double_ in
|
|
347
|
+
if let __unwrappedValue = self.__implementation.resizeHeight {
|
|
348
|
+
return bridge.create_std__optional_double_(__unwrappedValue)
|
|
349
|
+
} else {
|
|
350
|
+
return .init()
|
|
351
|
+
}
|
|
352
|
+
}()
|
|
353
|
+
}
|
|
354
|
+
@inline(__always)
|
|
355
|
+
set {
|
|
356
|
+
self.__implementation.resizeHeight = { () -> Double? in
|
|
357
|
+
if bridge.has_value_std__optional_double_(newValue) {
|
|
358
|
+
let __unwrapped = bridge.get_std__optional_double_(newValue)
|
|
359
|
+
return __unwrapped
|
|
360
|
+
} else {
|
|
361
|
+
return nil
|
|
362
|
+
}
|
|
363
|
+
}()
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
343
367
|
public final var overscan: bridge.std__optional_double_ {
|
|
344
368
|
@inline(__always)
|
|
345
369
|
get {
|
|
@@ -34,6 +34,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
34
34
|
prototype.registerHybridSetter("round", &HybridOneKeyImageSpec::setRound);
|
|
35
35
|
prototype.registerHybridGetter("resizeWidth", &HybridOneKeyImageSpec::getResizeWidth);
|
|
36
36
|
prototype.registerHybridSetter("resizeWidth", &HybridOneKeyImageSpec::setResizeWidth);
|
|
37
|
+
prototype.registerHybridGetter("resizeHeight", &HybridOneKeyImageSpec::getResizeHeight);
|
|
38
|
+
prototype.registerHybridSetter("resizeHeight", &HybridOneKeyImageSpec::setResizeHeight);
|
|
37
39
|
prototype.registerHybridGetter("overscan", &HybridOneKeyImageSpec::getOverscan);
|
|
38
40
|
prototype.registerHybridSetter("overscan", &HybridOneKeyImageSpec::setOverscan);
|
|
39
41
|
prototype.registerHybridGetter("loadingStrategy", &HybridOneKeyImageSpec::getLoadingStrategy);
|
|
@@ -80,6 +80,8 @@ namespace margelo::nitro::onekeyimage {
|
|
|
80
80
|
virtual void setRound(std::optional<bool> round) = 0;
|
|
81
81
|
virtual std::optional<double> getResizeWidth() = 0;
|
|
82
82
|
virtual void setResizeWidth(std::optional<double> resizeWidth) = 0;
|
|
83
|
+
virtual std::optional<double> getResizeHeight() = 0;
|
|
84
|
+
virtual void setResizeHeight(std::optional<double> resizeHeight) = 0;
|
|
83
85
|
virtual std::optional<double> getOverscan() = 0;
|
|
84
86
|
virtual void setOverscan(std::optional<double> overscan) = 0;
|
|
85
87
|
virtual std::optional<OneKeyImageLoadingStrategy> getLoadingStrategy() = 0;
|
|
@@ -30,6 +30,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
30
30
|
optimizeTos(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "optimizeTos", rawProps, sourceProps.optimizeTos)),
|
|
31
31
|
round(nitro::ReactProp<std::optional<bool>>::fromRawValue("OneKeyImage", "round", rawProps, sourceProps.round)),
|
|
32
32
|
resizeWidth(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeWidth", rawProps, sourceProps.resizeWidth)),
|
|
33
|
+
resizeHeight(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "resizeHeight", rawProps, sourceProps.resizeHeight)),
|
|
33
34
|
overscan(nitro::ReactProp<std::optional<double>>::fromRawValue("OneKeyImage", "overscan", rawProps, sourceProps.overscan)),
|
|
34
35
|
loadingStrategy(nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>>::fromRawValue("OneKeyImage", "loadingStrategy", rawProps, sourceProps.loadingStrategy)),
|
|
35
36
|
placeholderColor(nitro::ReactProp<std::optional<std::string>>::fromRawValue("OneKeyImage", "placeholderColor", rawProps, sourceProps.placeholderColor)),
|
|
@@ -52,6 +53,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
52
53
|
case hashString("optimizeTos"): return true;
|
|
53
54
|
case hashString("round"): return true;
|
|
54
55
|
case hashString("resizeWidth"): return true;
|
|
56
|
+
case hashString("resizeHeight"): return true;
|
|
55
57
|
case hashString("overscan"): return true;
|
|
56
58
|
case hashString("loadingStrategy"): return true;
|
|
57
59
|
case hashString("placeholderColor"): return true;
|
|
@@ -58,6 +58,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
58
58
|
nitro::ReactProp<std::optional<bool>> optimizeTos;
|
|
59
59
|
nitro::ReactProp<std::optional<bool>> round;
|
|
60
60
|
nitro::ReactProp<std::optional<double>> resizeWidth;
|
|
61
|
+
nitro::ReactProp<std::optional<double>> resizeHeight;
|
|
61
62
|
nitro::ReactProp<std::optional<double>> overscan;
|
|
62
63
|
nitro::ReactProp<std::optional<OneKeyImageLoadingStrategy>> loadingStrategy;
|
|
63
64
|
nitro::ReactProp<std::optional<std::string>> placeholderColor;
|
|
@@ -80,6 +81,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
80
81
|
optimizeTos.hasSameValue(other.optimizeTos) &&
|
|
81
82
|
round.hasSameValue(other.round) &&
|
|
82
83
|
resizeWidth.hasSameValue(other.resizeWidth) &&
|
|
84
|
+
resizeHeight.hasSameValue(other.resizeHeight) &&
|
|
83
85
|
overscan.hasSameValue(other.overscan) &&
|
|
84
86
|
loadingStrategy.hasSameValue(other.loadingStrategy) &&
|
|
85
87
|
placeholderColor.hasSameValue(other.placeholderColor) &&
|
|
@@ -103,6 +105,7 @@ namespace margelo::nitro::onekeyimage::views {
|
|
|
103
105
|
optimizeTos.isProvided() ||
|
|
104
106
|
round.isProvided() ||
|
|
105
107
|
resizeWidth.isProvided() ||
|
|
108
|
+
resizeHeight.isProvided() ||
|
|
106
109
|
overscan.isProvided() ||
|
|
107
110
|
loadingStrategy.isProvided() ||
|
|
108
111
|
placeholderColor.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.157",
|
|
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.157",
|
|
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,12 @@ export interface OneKeyImageNativeProps extends HybridViewProps {
|
|
|
47
47
|
round?: boolean;
|
|
48
48
|
/** Display width hint in layout units. Native applies the screen density. */
|
|
49
49
|
resizeWidth?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Display height hint in layout units. With `resizeWidth` it lets the
|
|
52
|
+
* pre-layout memory-cache probe derive the same decode thumbnail a preload
|
|
53
|
+
* with the same hints stored; omitted, the hint is a square of `resizeWidth`.
|
|
54
|
+
*/
|
|
55
|
+
resizeHeight?: number;
|
|
50
56
|
overscan?: number;
|
|
51
57
|
loadingStrategy?: OneKeyImageLoadingStrategy;
|
|
52
58
|
/** Theme-aware color used by static loading, error, and fallback states. */
|
package/src/index.tsx
CHANGED
|
@@ -155,6 +155,7 @@ export function OneKeyImage({
|
|
|
155
155
|
optimizeTos = true,
|
|
156
156
|
round = false,
|
|
157
157
|
resizeWidth,
|
|
158
|
+
resizeHeight,
|
|
158
159
|
overscan = 1.1,
|
|
159
160
|
loadingStrategy = OneKeyImageLoadingStrategy.STATIC,
|
|
160
161
|
placeholderColor,
|
|
@@ -176,7 +177,7 @@ export function OneKeyImage({
|
|
|
176
177
|
normalized?.headers ?? {}
|
|
177
178
|
)}|${resolvedCachePolicy}|${recyclingKey ?? ''}|${contentFit}|${
|
|
178
179
|
optimizeTos ? '1' : '0'
|
|
179
|
-
}|${resizeWidth ?? ''}|${overscan}`;
|
|
180
|
+
}|${resizeWidth ?? ''}|${resizeHeight ?? ''}|${overscan}`;
|
|
180
181
|
const hasSource = normalized != null;
|
|
181
182
|
const hasOverlay = placeholder != null || fallback != null;
|
|
182
183
|
type LoadState = {
|
|
@@ -373,6 +374,7 @@ export function OneKeyImage({
|
|
|
373
374
|
optimizeTos,
|
|
374
375
|
round,
|
|
375
376
|
resizeWidth,
|
|
377
|
+
resizeHeight,
|
|
376
378
|
overscan,
|
|
377
379
|
loadingStrategy:
|
|
378
380
|
placeholder == null ? loadingStrategy : OneKeyImageLoadingStrategy.NONE,
|