@onekeyfe/react-native-image 6.7.0-alpha.412 → 6.7.0-alpha.414
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/README.md +0 -12
- package/android/build.gradle +1 -3
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImageGlideRegistry.kt +1 -1
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyImagePackage.kt +1 -2
- package/ios/OneKeyImageCoderBridge.h +0 -4
- package/ios/OneKeyImageCoderBridge.m +0 -9
- package/lib/module/package.json +1 -6
- package/lib/nitrogen/generated/android/onekeyimage+autolinking.cmake +0 -4
- package/lib/nitrogen/generated/android/onekeyimageOnLoad.cpp +0 -18
- package/lib/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.cpp +0 -17
- package/lib/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.hpp +15 -32
- package/lib/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Umbrella.hpp +0 -5
- package/lib/nitrogen/generated/ios/OneKeyImageAutolinking.mm +0 -8
- package/lib/nitrogen/generated/ios/OneKeyImageAutolinking.swift +0 -12
- package/nitro.json +0 -10
- package/nitrogen/generated/android/onekeyimage+autolinking.cmake +0 -4
- package/nitrogen/generated/android/onekeyimageOnLoad.cpp +0 -18
- package/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.cpp +0 -17
- package/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Bridge.hpp +15 -32
- package/nitrogen/generated/ios/OneKeyImage-Swift-Cxx-Umbrella.hpp +0 -5
- package/nitrogen/generated/ios/OneKeyImageAutolinking.mm +0 -8
- package/nitrogen/generated/ios/OneKeyImageAutolinking.swift +0 -12
- package/package.json +7 -40
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyIcon.kt +0 -93
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeyNamedSVG.kt +0 -217
- package/android/src/main/java/com/margelo/nitro/onekeyimage/OneKeySVG.kt +0 -31
- package/ios/OneKeyIcon.swift +0 -90
- package/ios/OneKeyNamedSVG.swift +0 -282
- package/ios/tests/OneKeyIconTests.swift +0 -484
- package/lib/module/OneKeyIcon.nitro.js +0 -4
- package/lib/module/icon/assetUrls.js +0 -7
- package/lib/module/icon/dom.js +0 -21
- package/lib/module/icon/index.js +0 -29
- package/lib/module/icon/index.web.js +0 -32
- package/lib/module/icon/props.js +0 -22
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyIconSpec.cpp +0 -67
- package/lib/nitrogen/generated/android/c++/JHybridOneKeyIconSpec.hpp +0 -66
- package/lib/nitrogen/generated/android/c++/views/JHybridOneKeyIconStateUpdater.cpp +0 -79
- package/lib/nitrogen/generated/android/c++/views/JHybridOneKeyIconStateUpdater.hpp +0 -54
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyIconSpec.kt +0 -65
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyIconManager.kt +0 -96
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyIconStateUpdater.kt +0 -23
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyIconSpecSwift.cpp +0 -11
- package/lib/nitrogen/generated/ios/c++/HybridOneKeyIconSpecSwift.hpp +0 -89
- package/lib/nitrogen/generated/ios/c++/views/HybridOneKeyIconComponent.mm +0 -150
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyIconSpec.swift +0 -56
- package/lib/nitrogen/generated/ios/swift/HybridOneKeyIconSpec_cxx.swift +0 -193
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyIconSpec.cpp +0 -24
- package/lib/nitrogen/generated/shared/c++/HybridOneKeyIconSpec.hpp +0 -66
- package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyIconComponent.cpp +0 -36
- package/lib/nitrogen/generated/shared/c++/views/HybridOneKeyIconComponent.hpp +0 -88
- package/lib/nitrogen/generated/shared/json/OneKeyIconConfig.json +0 -11
- package/lib/typescript/src/OneKeyIcon.nitro.d.ts +0 -7
- package/lib/typescript/src/icon/assetUrls.d.ts +0 -2
- package/lib/typescript/src/icon/dom.d.ts +0 -3
- package/lib/typescript/src/icon/index.d.ts +0 -140
- package/lib/typescript/src/icon/index.web.d.ts +0 -134
- package/lib/typescript/src/icon/props.d.ts +0 -8
- package/nitrogen/generated/android/c++/JHybridOneKeyIconSpec.cpp +0 -67
- package/nitrogen/generated/android/c++/JHybridOneKeyIconSpec.hpp +0 -66
- package/nitrogen/generated/android/c++/views/JHybridOneKeyIconStateUpdater.cpp +0 -79
- package/nitrogen/generated/android/c++/views/JHybridOneKeyIconStateUpdater.hpp +0 -54
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/HybridOneKeyIconSpec.kt +0 -65
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyIconManager.kt +0 -96
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/onekeyimage/views/HybridOneKeyIconStateUpdater.kt +0 -23
- package/nitrogen/generated/ios/c++/HybridOneKeyIconSpecSwift.cpp +0 -11
- package/nitrogen/generated/ios/c++/HybridOneKeyIconSpecSwift.hpp +0 -89
- package/nitrogen/generated/ios/c++/views/HybridOneKeyIconComponent.mm +0 -150
- package/nitrogen/generated/ios/swift/HybridOneKeyIconSpec.swift +0 -56
- package/nitrogen/generated/ios/swift/HybridOneKeyIconSpec_cxx.swift +0 -193
- package/nitrogen/generated/shared/c++/HybridOneKeyIconSpec.cpp +0 -24
- package/nitrogen/generated/shared/c++/HybridOneKeyIconSpec.hpp +0 -66
- package/nitrogen/generated/shared/c++/views/HybridOneKeyIconComponent.cpp +0 -36
- package/nitrogen/generated/shared/c++/views/HybridOneKeyIconComponent.hpp +0 -88
- package/nitrogen/generated/shared/json/OneKeyIconConfig.json +0 -11
- package/scripts/configure-icon-imports.mjs +0 -7
- package/scripts/icon-fixtures.test.mjs +0 -398
- package/src/OneKeyIcon.nitro.ts +0 -8
- package/src/icon/assetUrls.ts +0 -4
- package/src/icon/dom.ts +0 -21
- package/src/icon/index.tsx +0 -38
- package/src/icon/index.web.tsx +0 -36
- package/src/icon/props.ts +0 -38
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
import UIKit
|
|
2
|
-
import XCTest
|
|
3
|
-
|
|
4
|
-
@testable import OneKeyImage
|
|
5
|
-
|
|
6
|
-
final class OneKeyIconTests: XCTestCase {
|
|
7
|
-
private func resolve(_ name: String, color: String = "rgba(255,0,0,0.5019607843137255)",
|
|
8
|
-
width: Int = 128, height: Int = 128, scale: CGFloat = 1) -> UIImage? {
|
|
9
|
-
let done = expectation(description: name)
|
|
10
|
-
let owner = NSObject()
|
|
11
|
-
var output: UIImage?
|
|
12
|
-
withExtendedLifetime(owner) {
|
|
13
|
-
OneKeyNamedSVG.shared.request(owner: owner, name: name, color: color,
|
|
14
|
-
width: width, height: height, scale: scale) { image in
|
|
15
|
-
output = image
|
|
16
|
-
done.fulfill()
|
|
17
|
-
}
|
|
18
|
-
wait(for: [done], timeout: 5)
|
|
19
|
-
}
|
|
20
|
-
return output
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
private func resolveRender(_ name: String, color: String = "rgba(0,0,255,1)", scale: CGFloat = 1) throws -> OneKeyNamedSVG.RenderResult {
|
|
24
|
-
let done = expectation(description: "Shape result")
|
|
25
|
-
let owner = NSObject(); var result: OneKeyNamedSVG.RenderResult?
|
|
26
|
-
OneKeyNamedSVG.shared.requestRender(owner: owner, name: name, color: color,
|
|
27
|
-
width: 128, height: 128, scale: scale) { result = $0; done.fulfill() }
|
|
28
|
-
withExtendedLifetime(owner) { wait(for: [done], timeout: 5) }
|
|
29
|
-
return try XCTUnwrap(result)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private func draw(_ view: UIImageView) -> UIImage {
|
|
33
|
-
let format = UIGraphicsImageRendererFormat(); format.scale = view.window?.screen.scale ?? 1
|
|
34
|
-
return UIGraphicsImageRenderer(size: view.bounds.size, format: format).image { _ in
|
|
35
|
-
view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
private func field<T>(_ name: String, as type: T.Type = T.self) throws -> T {
|
|
40
|
-
let value = try XCTUnwrap(Mirror(reflecting: OneKeyNamedSVG.shared).children.first { $0.label == name }?.value)
|
|
41
|
-
return try XCTUnwrap(value as? T)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private func eventually(_ description: String, _ condition: () -> Bool) {
|
|
45
|
-
let deadline = Date().addingTimeInterval(5)
|
|
46
|
-
while !condition(), Date() < deadline { RunLoop.main.run(until: Date().addingTimeInterval(0.01)) }
|
|
47
|
-
XCTAssertTrue(condition(), description)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
private func save(_ image: UIImage, name: String) throws {
|
|
51
|
-
guard let directory = ProcessInfo.processInfo.environment["ICON_EVIDENCE_DIR"] else { return }
|
|
52
|
-
try image.pngData()?.write(to: URL(fileURLWithPath: directory).appendingPathComponent(name + ".png"))
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
private func pixels(_ image: UIImage) throws -> [UInt8] {
|
|
56
|
-
let cgImage = try XCTUnwrap(image.cgImage)
|
|
57
|
-
let width = cgImage.width, height = cgImage.height
|
|
58
|
-
var bytes = [UInt8](repeating: 0, count: width * height * 4)
|
|
59
|
-
let context = try XCTUnwrap(CGContext(data: &bytes, width: width, height: height,
|
|
60
|
-
bitsPerComponent: 8, bytesPerRow: width * 4, space: CGColorSpaceCreateDeviceRGB(),
|
|
61
|
-
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue))
|
|
62
|
-
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
|
|
63
|
-
return bytes
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
func testNamedColorEndpointsRetainCSSAlpha() throws {
|
|
67
|
-
for (alpha, expected) in [("1", 255), ("0.5", 128), ("0", 0)] {
|
|
68
|
-
let image = try XCTUnwrap(resolve("DotVerSolid", color: "rgba(255,0,0,\(alpha))", width: 192, height: 192))
|
|
69
|
-
let bytes = try pixels(image)
|
|
70
|
-
let center = (96 * 192 + 96) * 4
|
|
71
|
-
XCTAssertEqual(Int(bytes[center + 3]), expected, accuracy: 1)
|
|
72
|
-
XCTAssertEqual(Int(bytes[center]), expected, accuracy: 1)
|
|
73
|
-
XCTAssertEqual(bytes[center + 1], 0); XCTAssertEqual(bytes[center + 2], 0)
|
|
74
|
-
try save(image, name: "named-alpha-" + alpha)
|
|
75
|
-
}
|
|
76
|
-
let mixed = try XCTUnwrap(resolve("OnekeyTextIllus", color: "rgba(255,0,0,0)", width: 128, height: 128))
|
|
77
|
-
let bytes = try pixels(mixed)
|
|
78
|
-
XCTAssertTrue(stride(from: 0, to: bytes.count, by: 4).contains { bytes[$0 + 1] > bytes[$0] && bytes[$0 + 3] == 255 })
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
func testAllBundledSDKFixturesDecode() throws {
|
|
82
|
-
let ownerBundle = Bundle(for: HybridOneKeyIcon.self)
|
|
83
|
-
let url = try XCTUnwrap(ownerBundle.url(forResource: "OneKeyIcons", withExtension: "bundle")
|
|
84
|
-
?? Bundle.main.url(forResource: "OneKeyIcons", withExtension: "bundle"))
|
|
85
|
-
let bundle = try XCTUnwrap(Bundle(url: url))
|
|
86
|
-
let manifestURL = try XCTUnwrap(bundle.url(forResource: "manifest", withExtension: "json"))
|
|
87
|
-
let manifest = try XCTUnwrap(JSONSerialization.jsonObject(with: Data(contentsOf: manifestURL)) as? [String: Any])
|
|
88
|
-
XCTAssertEqual(manifest.count, 63)
|
|
89
|
-
let all = expectation(description: "All named resources")
|
|
90
|
-
all.expectedFulfillmentCount = manifest.count
|
|
91
|
-
let owners = manifest.keys.sorted().map { _ in NSObject() }
|
|
92
|
-
var failed: [String] = []
|
|
93
|
-
withExtendedLifetime(owners) {
|
|
94
|
-
for (index, name) in manifest.keys.sorted().enumerated() {
|
|
95
|
-
OneKeyNamedSVG.shared.request(owner: owners[index], name: name, color: "rgba(255,0,0,0.5019607843137255)",
|
|
96
|
-
width: 128, height: 128, scale: 1) { image in
|
|
97
|
-
if image == nil { failed.append(name) }
|
|
98
|
-
all.fulfill()
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
wait(for: [all], timeout: 60)
|
|
102
|
-
}
|
|
103
|
-
XCTAssertEqual(failed, [])
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
func testMixedColorTinyAlphaAndUnknownName() throws {
|
|
107
|
-
XCTAssertNil(resolve("MissingIcon"))
|
|
108
|
-
let image = try XCTUnwrap(resolve("OnekeyTextIllus", color: "rgba(255,0,0,0)"))
|
|
109
|
-
let cgImage = try XCTUnwrap(image.cgImage)
|
|
110
|
-
var pixels = [UInt8](repeating: 0, count: 128 * 128 * 4)
|
|
111
|
-
let context = try XCTUnwrap(CGContext(data: &pixels, width: 128, height: 128,
|
|
112
|
-
bitsPerComponent: 8, bytesPerRow: 128 * 4, space: CGColorSpaceCreateDeviceRGB(),
|
|
113
|
-
bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue))
|
|
114
|
-
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: 128, height: 128))
|
|
115
|
-
var green = 0, red = 0
|
|
116
|
-
for index in stride(from: 0, to: pixels.count, by: 4) where pixels[index + 3] > 0 {
|
|
117
|
-
if pixels[index + 1] > pixels[index] { green += 1 }
|
|
118
|
-
if pixels[index] > pixels[index + 1] { red += 1 }
|
|
119
|
-
}
|
|
120
|
-
XCTAssertGreaterThan(green, 0)
|
|
121
|
-
XCTAssertEqual(red, 0)
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
func testCacheAndCoalescedQueueBounds() throws {
|
|
125
|
-
let stateLock: NSLock = try field("lock")
|
|
126
|
-
let metadataLock: NSLock = try field("metadataLock")
|
|
127
|
-
let blockerOwners = (0..<4).map { _ in NSObject() }
|
|
128
|
-
let owner = NSObject()
|
|
129
|
-
let blockers = expectation(description: "Blocked decodes drain after metadata release")
|
|
130
|
-
blockers.expectedFulfillmentCount = blockerOwners.count
|
|
131
|
-
metadataLock.lock()
|
|
132
|
-
do {
|
|
133
|
-
defer { metadataLock.unlock() }
|
|
134
|
-
for blocker in blockerOwners {
|
|
135
|
-
OneKeyNamedSVG.shared.request(owner: blocker, name: "DotVerSolid", color: "rgba(0,0,255,1)",
|
|
136
|
-
width: 24, height: 24, scale: 1) { _ in blockers.fulfill() }
|
|
137
|
-
}
|
|
138
|
-
eventually("Exactly two production workers are blocked at metadata") {
|
|
139
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
140
|
-
return (try? self.field("workers", as: Int.self)) == 2
|
|
141
|
-
}
|
|
142
|
-
for _ in 0..<100 {
|
|
143
|
-
OneKeyNamedSVG.shared.request(owner: owner, name: "DotVerSolid", color: "rgba(255,0,0,1)",
|
|
144
|
-
width: 24, height: 24, scale: 1) { _ in XCTFail("Cancelled coalesced request completed") }
|
|
145
|
-
}
|
|
146
|
-
let (order, keys, workers): ([ObjectIdentifier], [ObjectIdentifier], Int) = try {
|
|
147
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
148
|
-
let order: [ObjectIdentifier] = try field("order")
|
|
149
|
-
let pending: Any = try field("pending")
|
|
150
|
-
print("ICON_QUEUE_REFLECTION type=\(Swift.type(of: pending)) style=\(String(describing: Mirror(reflecting: pending).displayStyle))")
|
|
151
|
-
XCTAssertEqual(Mirror(reflecting: pending).displayStyle, .dictionary)
|
|
152
|
-
let keys = Mirror(reflecting: pending).children.compactMap {
|
|
153
|
-
Mirror(reflecting: $0.value).children.first?.value as? ObjectIdentifier
|
|
154
|
-
}
|
|
155
|
-
return (order, keys, try field("workers"))
|
|
156
|
-
}()
|
|
157
|
-
XCTAssertEqual(order.filter { $0 == ObjectIdentifier(owner) }.count, 1)
|
|
158
|
-
XCTAssertEqual(keys.filter { $0 == ObjectIdentifier(owner) }.count, 1)
|
|
159
|
-
XCTAssertLessThanOrEqual(workers, 2)
|
|
160
|
-
print("ICON_QUEUE_BOUND ownerOrder=\(order.filter { $0 == ObjectIdentifier(owner) }.count) ownerPending=\(keys.filter { $0 == ObjectIdentifier(owner) }.count) workers=\(workers)")
|
|
161
|
-
OneKeyNamedSVG.shared.cancel(owner: owner)
|
|
162
|
-
let cancelledOrder: [ObjectIdentifier] = try {
|
|
163
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
164
|
-
return try field("order")
|
|
165
|
-
}()
|
|
166
|
-
XCTAssertFalse(cancelledOrder.contains(ObjectIdentifier(owner)))
|
|
167
|
-
}
|
|
168
|
-
withExtendedLifetime(blockerOwners) { wait(for: [blockers], timeout: 5) }
|
|
169
|
-
eventually("All workers completed") {
|
|
170
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
171
|
-
return (try? self.field("workers", as: Int.self)) == 0
|
|
172
|
-
}
|
|
173
|
-
var firstSizeImage: UIImage?
|
|
174
|
-
var lastSizeImage: UIImage?
|
|
175
|
-
for width in 24..<174 {
|
|
176
|
-
let image = try XCTUnwrap(resolve("DotVerSolid", color: "rgba(0,0,0,1)", width: width, height: 24))
|
|
177
|
-
if width == 24 { firstSizeImage = image }
|
|
178
|
-
lastSizeImage = image
|
|
179
|
-
}
|
|
180
|
-
let smallCount: Int = try {
|
|
181
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
182
|
-
let cache: [String: OneKeyNamedSVG.RenderResult] = try field("cache")
|
|
183
|
-
return cache.count
|
|
184
|
-
}()
|
|
185
|
-
XCTAssertEqual(smallCount, 128)
|
|
186
|
-
let sizeCache: [String: OneKeyNamedSVG.RenderResult] = try field("cache")
|
|
187
|
-
XCTAssertFalse(sizeCache.values.contains { $0.image === firstSizeImage })
|
|
188
|
-
XCTAssertTrue(sizeCache.values.contains { $0.image === lastSizeImage })
|
|
189
|
-
_ = try XCTUnwrap(resolve("AppleBrand", width: 1024, height: 1024))
|
|
190
|
-
_ = try XCTUnwrap(resolve("BotIllus", width: 1024, height: 1024))
|
|
191
|
-
let uncached = try XCTUnwrap(resolve("BotIllus", width: 1536, height: 1536))
|
|
192
|
-
let (cache, storedBytes): ([String: OneKeyNamedSVG.RenderResult], Int) = try {
|
|
193
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
194
|
-
return (try field("cache"), try field("bytes"))
|
|
195
|
-
}()
|
|
196
|
-
let actualBytes = cache.values.reduce(0) { $0 + ($1.image.cgImage?.bytesPerRow ?? 0) * ($1.image.cgImage?.height ?? 0) }
|
|
197
|
-
XCTAssertLessThanOrEqual(cache.count, 128)
|
|
198
|
-
XCTAssertLessThanOrEqual(actualBytes, 8_388_608)
|
|
199
|
-
XCTAssertEqual(storedBytes, actualBytes)
|
|
200
|
-
XCTAssertFalse(cache.values.contains { $0.image === uncached })
|
|
201
|
-
let a = try resolveRender("DotVerSolid")
|
|
202
|
-
let same = try resolveRender("DotVerSolid", color: "rgba(255,0,0,1)")
|
|
203
|
-
let otherScale = try resolveRender("DotVerSolid", scale: 2)
|
|
204
|
-
XCTAssertTrue(a.image === same.image)
|
|
205
|
-
XCTAssertFalse(a.image === otherScale.image)
|
|
206
|
-
XCTAssertNil(resolve("DotVerSolid", width: 4097))
|
|
207
|
-
XCTAssertNil(resolve("DotVerSolid", width: 0))
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
private func assertSemanticPixels(_ actual: UIImage, _ expected: UIImage, name: String, alpha: Double) throws {
|
|
211
|
-
let a = try pixels(actual), b = try pixels(expected)
|
|
212
|
-
let width = try XCTUnwrap(actual.cgImage).width, height = try XCTUnwrap(actual.cgImage).height
|
|
213
|
-
XCTAssertEqual(a.count, b.count)
|
|
214
|
-
// These fixture modes are independent source facts, not production classification output.
|
|
215
|
-
let single = name == "DotVerSolid"
|
|
216
|
-
let multiple = name == "ChartPositionOutline" || name == "LimitOrderOutline"
|
|
217
|
-
let maximum = zip(a, b).map { abs(Int($0)-Int($1)) }.max() ?? 0
|
|
218
|
-
if !single && !multiple { XCTAssertLessThanOrEqual(maximum, 1, name); return }
|
|
219
|
-
var alphaMaximum = 0, flatMaximum = 0, colorMaximum = 0
|
|
220
|
-
var actualMass = 0, rawMass = 0, covered = 0, alphaError = 0
|
|
221
|
-
var actualBox = [width, height, -1, -1], rawBox = actualBox
|
|
222
|
-
for y in 0..<height { for x in 0..<width {
|
|
223
|
-
let offset = (y * width+x)*4, aa = Int(a[offset+3]), ba = Int(b[offset+3])
|
|
224
|
-
actualMass += aa; rawMass += ba; alphaMaximum = max(alphaMaximum, abs(aa-ba))
|
|
225
|
-
if aa > 0 || ba > 0 { covered += 1; alphaError += abs(aa-ba) }
|
|
226
|
-
for (values, isActual) in [(aa, true), (ba, false)] where values > 0 {
|
|
227
|
-
var box = isActual ? actualBox : rawBox
|
|
228
|
-
box = [min(box[0],x), min(box[1],y), max(box[2],x), max(box[3],y)]
|
|
229
|
-
if isActual { actualBox = box } else { rawBox = box }
|
|
230
|
-
}
|
|
231
|
-
for (channel, rgb) in [63,111,199].enumerated() {
|
|
232
|
-
colorMaximum = max(colorMaximum, abs(Int(a[offset+channel])-Int((Double(rgb)*Double(aa)/255).rounded())))
|
|
233
|
-
}
|
|
234
|
-
if ba > 0 && x >= 2 && y >= 2 && x < width-2 && y < height-2 {
|
|
235
|
-
var flat = true
|
|
236
|
-
for dy in -2...2 { for dx in -2...2 { for channel in 0..<4 {
|
|
237
|
-
if b[((y+dy)*width+x+dx)*4+channel] != b[offset+channel] { flat = false }
|
|
238
|
-
} } }
|
|
239
|
-
if flat { for channel in 0..<4 { flatMaximum = max(flatMaximum, abs(Int(a[offset+channel])-Int(b[offset+channel]))) } }
|
|
240
|
-
}
|
|
241
|
-
} }
|
|
242
|
-
XCTAssertLessThanOrEqual(colorMaximum, 1, "Dynamic RGB follows requested color times actual alpha")
|
|
243
|
-
if multiple || alpha == 1 { XCTAssertLessThanOrEqual(alphaMaximum, 1, name) }
|
|
244
|
-
else if alpha == 0 { XCTAssertEqual(actualMass, 0, name) }
|
|
245
|
-
else {
|
|
246
|
-
XCTAssertLessThanOrEqual(flatMaximum, 1, "Raw flat interiors remain equivalent")
|
|
247
|
-
XCTAssertLessThanOrEqual(alphaMaximum, 16, "Only bounded single-paint antialiasing differences")
|
|
248
|
-
XCTAssertLessThanOrEqual(Double(abs(actualMass-rawMass))/Double(max(1,rawMass)), 0.02)
|
|
249
|
-
XCTAssertLessThanOrEqual(Double(alphaError)/Double(max(1,covered)), 2)
|
|
250
|
-
for (left,right) in zip(actualBox,rawBox) { XCTAssertLessThanOrEqual(abs(left-right), 1) }
|
|
251
|
-
}
|
|
252
|
-
print("ICON_SEMANTIC name=\(name) alpha=\(alpha) rawMax=\(maximum) alphaMax=\(alphaMaximum) flatMax=\(flatMaximum) tintMax=\(colorMaximum) massDelta=\(actualMass-rawMass)")
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
func testRenderedShapesMatchIndependentRawDecoder() throws {
|
|
256
|
-
guard UIApplication.perform(NSSelectorFromString("sharedApplication"))?.takeUnretainedValue() as? UIApplication != nil else {
|
|
257
|
-
throw XCTSkip("A UIApplication host is required for consumer pixel comparison")
|
|
258
|
-
}
|
|
259
|
-
let owner = Bundle(for: HybridOneKeyIcon.self)
|
|
260
|
-
let bundle = try XCTUnwrap(Bundle(url: try XCTUnwrap(owner.url(forResource: "OneKeyIcons", withExtension: "bundle")
|
|
261
|
-
?? Bundle.main.url(forResource: "OneKeyIcons", withExtension: "bundle"))))
|
|
262
|
-
let window = UIWindow(frame: UIScreen.main.bounds); let controller = UIViewController()
|
|
263
|
-
window.rootViewController = controller; window.makeKeyAndVisible(); defer { window.isHidden = true }
|
|
264
|
-
for name in ["DotVerSolid", "ChartPositionOutline", "LimitOrderOutline", "BotIllus", "OnekeyTextIllus", "BadgeVerifiedSolid"] {
|
|
265
|
-
for alpha in ["0.0", "0.5", "1.0"] {
|
|
266
|
-
let color = "rgba(63,111,199,\(alpha))"
|
|
267
|
-
let icon = HybridOneKeyIcon(); let view = try XCTUnwrap(icon.view as? UIImageView)
|
|
268
|
-
view.frame = CGRect(x: 0, y: 80, width: 64, height: 64); controller.view.addSubview(view)
|
|
269
|
-
icon.iconName = name; icon.resolvedColor = color; icon.afterUpdate()
|
|
270
|
-
eventually("Raw baseline sample ready") { view.image != nil }
|
|
271
|
-
let actual = draw(view)
|
|
272
|
-
let source = try String(contentsOf: XCTUnwrap(bundle.url(forResource: name, withExtension: "svg")), encoding: .utf8)
|
|
273
|
-
let data = try XCTUnwrap(source.replacingOccurrences(of: "currentColor", with: color).data(using: .utf8))
|
|
274
|
-
let size = CGSize(width: 64 * window.screen.scale, height: 64 * window.screen.scale)
|
|
275
|
-
let decoded = try XCTUnwrap(OneKeyImageCoderBridge.decodeSVG(data, pixelSize: size))
|
|
276
|
-
let format = UIGraphicsImageRendererFormat(); format.scale = 1
|
|
277
|
-
let expected = UIGraphicsImageRenderer(size: size, format: format).image { _ in
|
|
278
|
-
let ratio = min(size.width / decoded.size.width, size.height / decoded.size.height)
|
|
279
|
-
let fitted = CGSize(width: decoded.size.width * ratio, height: decoded.size.height * ratio)
|
|
280
|
-
decoded.draw(in: CGRect(x: (size.width-fitted.width)/2, y: (size.height-fitted.height)/2, width: fitted.width, height: fitted.height))
|
|
281
|
-
}
|
|
282
|
-
try assertSemanticPixels(actual, expected, name: name, alpha: try XCTUnwrap(Double(alpha)))
|
|
283
|
-
try save(actual, name: "shape-actual-\(name)-\(alpha)")
|
|
284
|
-
try save(expected, name: "shape-raw-\(name)-\(alpha)")
|
|
285
|
-
icon.prepareForRecycle(); view.removeFromSuperview()
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
let edge = Int(64 * window.screen.scale)
|
|
289
|
-
let size = CGSize(width: edge, height: edge)
|
|
290
|
-
func raster(_ body: String) throws -> UIImage {
|
|
291
|
-
let source = "<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'>\(body)</svg>"
|
|
292
|
-
let decoded = try XCTUnwrap(OneKeyImageCoderBridge.decodeSVG(Data(source.utf8), pixelSize: size))
|
|
293
|
-
let format = UIGraphicsImageRendererFormat(); format.scale = 1
|
|
294
|
-
return UIGraphicsImageRenderer(size: size, format: format).image { _ in decoded.draw(in: CGRect(origin: .zero, size: size)) }
|
|
295
|
-
}
|
|
296
|
-
let overlap = "<rect width='16' height='24' fill='rgba(0,0,0,0.5)'/><rect x='8' width='16' height='24' fill='rgba(0,0,0,0.5)'/>"
|
|
297
|
-
let mask = try raster(overlap)
|
|
298
|
-
let result = OneKeyNamedSVG.RenderResult(image: mask, mode: .multiple, sourceIdentity: "test-overlap", maskAlpha: 0.5)
|
|
299
|
-
let probe = UIImageView(frame: CGRect(x: 0,y: 80,width: 64,height: 64)); controller.view.addSubview(probe)
|
|
300
|
-
probe.image = result.image.withRenderingMode(.alwaysTemplate); probe.tintColor = result.tintColor("rgba(255,0,0,0.5)")
|
|
301
|
-
let rendered = draw(probe), actual = try pixels(rendered)
|
|
302
|
-
let raw = try raster(overlap.replacingOccurrences(of: "rgba(0,0,0,0.5)", with: "rgba(255,0,0,0.5)"))
|
|
303
|
-
let expected = try pixels(raw), center = ((edge/2)*edge+edge/2)*4
|
|
304
|
-
XCTAssertEqual(expected[center+3], 192); XCTAssertEqual(actual[center+3], 192)
|
|
305
|
-
let opacityMask = try raster("<rect width='24' height='24' fill='rgba(0,0,0,1.0)' fill-opacity='0.4'/>")
|
|
306
|
-
let single = OneKeyNamedSVG.RenderResult(image: opacityMask, mode: .single, sourceIdentity: "test-source-opacity", maskAlpha: 1)
|
|
307
|
-
probe.image = single.image.withRenderingMode(.alwaysTemplate); probe.tintColor = single.tintColor("rgba(255,0,0,0.5)")
|
|
308
|
-
let opacityActual = try pixels(draw(probe))
|
|
309
|
-
XCTAssertEqual(Int(opacityActual[center+3]), 51, accuracy: 1)
|
|
310
|
-
probe.removeFromSuperview()
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
func testShapeTintAndPendingColorRetention() throws {
|
|
314
|
-
guard UIApplication.perform(NSSelectorFromString("sharedApplication"))?.takeUnretainedValue() as? UIApplication != nil else {
|
|
315
|
-
throw XCTSkip("A UIApplication host is required for actual tint drawing")
|
|
316
|
-
}
|
|
317
|
-
let window = UIWindow(frame: UIScreen.main.bounds); let controller = UIViewController()
|
|
318
|
-
window.rootViewController = controller; window.makeKeyAndVisible(); defer { window.isHidden = true }
|
|
319
|
-
let icon = HybridOneKeyIcon(); let view = try XCTUnwrap(icon.view as? UIImageView)
|
|
320
|
-
view.frame = CGRect(x: 0, y: 80, width: 64, height: 64); controller.view.addSubview(view)
|
|
321
|
-
icon.iconName = "DotVerSolid"; icon.resolvedColor = "rgba(255,0,0,1)"; icon.afterUpdate()
|
|
322
|
-
eventually("Initial shape mask") { view.image != nil }
|
|
323
|
-
let mask = try XCTUnwrap(view.image)
|
|
324
|
-
let other = HybridOneKeyIcon(); let otherView = try XCTUnwrap(other.view as? UIImageView)
|
|
325
|
-
otherView.frame = CGRect(x: 80, y: 80, width: 64, height: 64); controller.view.addSubview(otherView)
|
|
326
|
-
other.iconName = "DotVerSolid"; other.resolvedColor = "rgba(0,0,255,1)"; other.afterUpdate()
|
|
327
|
-
eventually("Second view shares cached shape") { otherView.image != nil }
|
|
328
|
-
XCTAssertTrue(mask.cgImage === otherView.image?.cgImage)
|
|
329
|
-
let stateLock: NSLock = try field("lock")
|
|
330
|
-
eventually("Initial shape requests drained") {
|
|
331
|
-
stateLock.lock(); defer { stateLock.unlock() }
|
|
332
|
-
return (try? self.field("workers", as: Int.self)) == 0
|
|
333
|
-
}
|
|
334
|
-
view.isHidden = true; XCTAssertTrue(view.image === mask)
|
|
335
|
-
view.isHidden = false; XCTAssertTrue(view.image === mask)
|
|
336
|
-
let metadataLock: NSLock = try field("metadataLock")
|
|
337
|
-
metadataLock.lock()
|
|
338
|
-
do {
|
|
339
|
-
defer { metadataLock.unlock() }
|
|
340
|
-
for color in ["rgba(0,0,255,1)", "rgba(0,255,0,0.5)"] {
|
|
341
|
-
icon.resolvedColor = color; icon.afterUpdate()
|
|
342
|
-
XCTAssertTrue(view.image === mask, "Immediate tint retains the immutable image")
|
|
343
|
-
}
|
|
344
|
-
let bytes = try pixels(draw(view)); let width = Int(64 * window.screen.scale)
|
|
345
|
-
let center = (width / 2 * width + width / 2) * 4
|
|
346
|
-
XCTAssertEqual(bytes[center], 0); XCTAssertEqual(bytes[center + 2], 0)
|
|
347
|
-
XCTAssertEqual(Int(bytes[center + 1]), 128, accuracy: 1)
|
|
348
|
-
XCTAssertEqual(Int(bytes[center + 3]), 128, accuracy: 1)
|
|
349
|
-
let otherBytes = try pixels(draw(otherView))
|
|
350
|
-
XCTAssertEqual(otherBytes[center], 0); XCTAssertEqual(otherBytes[center + 1], 0)
|
|
351
|
-
XCTAssertEqual(otherBytes[center + 2], 255); XCTAssertEqual(otherBytes[center + 3], 255)
|
|
352
|
-
stateLock.lock()
|
|
353
|
-
defer { stateLock.unlock() }
|
|
354
|
-
let pending: Any = try field("pending")
|
|
355
|
-
XCTAssertEqual(Mirror(reflecting: pending).children.count, 0, "RGB/alpha single-paint tint submits no worker request")
|
|
356
|
-
XCTAssertEqual(try field("workers", as: Int.self), 0, "No in-flight worker can hide a submitted request")
|
|
357
|
-
}
|
|
358
|
-
icon.iconName = "ChartPositionOutline"; icon.resolvedColor = "rgba(255,0,0,1)"; icon.afterUpdate()
|
|
359
|
-
eventually("Multiple-paint shape") { view.image != nil }
|
|
360
|
-
let multiple = try XCTUnwrap(view.image)
|
|
361
|
-
icon.resolvedColor = "rgba(0,0,255,1)"; icon.afterUpdate(); XCTAssertTrue(view.image === multiple)
|
|
362
|
-
metadataLock.lock()
|
|
363
|
-
do {
|
|
364
|
-
defer { metadataLock.unlock() }
|
|
365
|
-
icon.resolvedColor = "rgba(0,255,0,0.5)"; icon.afterUpdate()
|
|
366
|
-
XCTAssertTrue(view.image === multiple, "New mask alpha retains the successful old image")
|
|
367
|
-
icon.resolvedColor = "invalid"; icon.afterUpdate(); XCTAssertNil(view.image)
|
|
368
|
-
}
|
|
369
|
-
RunLoop.main.run(until: Date().addingTimeInterval(0.1)); XCTAssertNil(view.image)
|
|
370
|
-
icon.iconName = "BotIllus"; icon.resolvedColor = "rgba(255,0,0,1)"; icon.afterUpdate()
|
|
371
|
-
eventually("Fixed original") { view.image != nil }
|
|
372
|
-
let fixed = try XCTUnwrap(view.image)
|
|
373
|
-
icon.resolvedColor = "rgba(0,0,255,0)"; icon.afterUpdate(); XCTAssertTrue(view.image === fixed)
|
|
374
|
-
icon.iconName = "OnekeyTextIllus"; icon.afterUpdate()
|
|
375
|
-
eventually("Mixed original") { view.image != nil }
|
|
376
|
-
let mixed = try XCTUnwrap(view.image)
|
|
377
|
-
metadataLock.lock()
|
|
378
|
-
do {
|
|
379
|
-
defer { metadataLock.unlock() }
|
|
380
|
-
icon.resolvedColor = "rgba(255,0,0,0.5)"; icon.afterUpdate(); XCTAssertTrue(view.image === mixed)
|
|
381
|
-
icon.iconName = "MissingIcon"; icon.afterUpdate(); XCTAssertNil(view.image)
|
|
382
|
-
}
|
|
383
|
-
RunLoop.main.run(until: Date().addingTimeInterval(0.1)); XCTAssertNil(view.image)
|
|
384
|
-
icon.prepareForRecycle(); other.prepareForRecycle(); XCTAssertNil(view.image)
|
|
385
|
-
let one = try resolveRender("DotVerSolid"); XCTAssertEqual(one.mode, .single)
|
|
386
|
-
let multi = try resolveRender("ChartPositionOutline", color: "rgba(0,0,255,0.5)"); XCTAssertEqual(multi.mode, .multiple)
|
|
387
|
-
XCTAssertTrue(multi.canTint("rgba(255,0,0,0.5)")); XCTAssertFalse(multi.canTint("rgba(255,0,0,1)"))
|
|
388
|
-
XCTAssertEqual(try resolveRender("BotIllus").mode, .fixed)
|
|
389
|
-
XCTAssertEqual(try resolveRender("OnekeyTextIllus").mode, .raster)
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
func testProductionViewLifecycleAndRepresentativeRendering() throws {
|
|
393
|
-
guard let application = UIApplication.perform(NSSelectorFromString("sharedApplication"))?.takeUnretainedValue() as? UIApplication else {
|
|
394
|
-
throw XCTSkip("A real UIApplication host is required for window lifecycle acceptance")
|
|
395
|
-
}
|
|
396
|
-
XCTAssertTrue(Thread.isMainThread)
|
|
397
|
-
XCTAssertEqual(application.applicationState, .active)
|
|
398
|
-
let window = UIWindow(frame: UIScreen.main.bounds)
|
|
399
|
-
let controller = UIViewController()
|
|
400
|
-
controller.view.backgroundColor = UIColor(white: 0.125, alpha: 1)
|
|
401
|
-
window.rootViewController = controller
|
|
402
|
-
window.makeKeyAndVisible()
|
|
403
|
-
XCTAssertTrue(window.isKeyWindow)
|
|
404
|
-
XCTAssertFalse(window.isHidden)
|
|
405
|
-
defer { window.isHidden = true }
|
|
406
|
-
let icon = HybridOneKeyIcon()
|
|
407
|
-
let view = try XCTUnwrap(icon.view as? UIImageView)
|
|
408
|
-
view.frame = CGRect(x: 8, y: 60, width: 64, height: 64)
|
|
409
|
-
controller.view.addSubview(view)
|
|
410
|
-
XCTAssertTrue(view.window === window)
|
|
411
|
-
for index in 0..<100 {
|
|
412
|
-
icon.iconName = index.isMultiple(of: 2) ? "BotIllus" : "DotVerSolid"
|
|
413
|
-
icon.resolvedColor = "rgba(255,0,0,1)"
|
|
414
|
-
icon.afterUpdate()
|
|
415
|
-
}
|
|
416
|
-
icon.iconName = "DotVerSolid"; icon.resolvedColor = "rgba(0,0,255,0.5019607843137255)"; icon.afterUpdate()
|
|
417
|
-
eventually("Final blue view image displayed") { view.image != nil }
|
|
418
|
-
let blue = draw(view)
|
|
419
|
-
let bytes = try pixels(blue)
|
|
420
|
-
var blueCount = 0, redCount = 0
|
|
421
|
-
for index in stride(from: 0, to: bytes.count, by: 4) where bytes[index + 3] > 0 {
|
|
422
|
-
if bytes[index + 2] > bytes[index] { blueCount += 1 }
|
|
423
|
-
if bytes[index] > bytes[index + 2] { redCount += 1 }
|
|
424
|
-
}
|
|
425
|
-
XCTAssertGreaterThan(blueCount, 0); XCTAssertEqual(redCount, 0)
|
|
426
|
-
let maximumAlpha = stride(from: 3, to: bytes.count, by: 4).map { bytes[$0] }.max() ?? 0
|
|
427
|
-
let cgImage = try XCTUnwrap(blue.cgImage)
|
|
428
|
-
let interiorAlpha = bytes[((cgImage.height / 2) * cgImage.width + cgImage.width / 2) * 4 + 3]
|
|
429
|
-
print("ICON_ALPHA_PROBE solidInteriorAlpha=\(interiorAlpha) resampledEdgeMaximumAlpha=\(maximumAlpha)")
|
|
430
|
-
for y in [cgImage.height / 6, cgImage.height / 2, cgImage.height * 5 / 6] {
|
|
431
|
-
let offset = (y * cgImage.width + cgImage.width / 2) * 4
|
|
432
|
-
XCTAssertEqual(bytes[offset], 0)
|
|
433
|
-
XCTAssertEqual(bytes[offset + 1], 0)
|
|
434
|
-
XCTAssertTrue((127...128).contains(Int(bytes[offset + 3])))
|
|
435
|
-
XCTAssertEqual(bytes[offset + 2], bytes[offset + 3])
|
|
436
|
-
}
|
|
437
|
-
XCTAssertEqual(bytes[3], 0)
|
|
438
|
-
try save(blue, name: "ios-native-view-blue")
|
|
439
|
-
view.frame.size = CGSize(width: 96, height: 64); view.setNeedsLayout(); view.layoutIfNeeded()
|
|
440
|
-
eventually("Resized raster is current") { view.image?.cgImage?.width == Int(ceil(96 * window.screen.scale)) }
|
|
441
|
-
XCTAssertEqual(view.image?.cgImage?.height, Int(ceil(64 * window.screen.scale)))
|
|
442
|
-
view.frame.size = .zero; view.setNeedsLayout(); view.layoutIfNeeded()
|
|
443
|
-
XCTAssertNil(view.image)
|
|
444
|
-
view.frame.size = CGSize(width: 64, height: 64); view.setNeedsLayout(); view.layoutIfNeeded()
|
|
445
|
-
eventually("Restored layout decodes") { view.image != nil }
|
|
446
|
-
icon.iconName = "MissingIcon"; icon.afterUpdate(); XCTAssertNil(view.image)
|
|
447
|
-
icon.iconName = "BotIllus"; icon.afterUpdate()
|
|
448
|
-
view.removeFromSuperview(); XCTAssertNil(view.window); XCTAssertNil(view.image)
|
|
449
|
-
RunLoop.main.run(until: Date().addingTimeInterval(0.1)); XCTAssertNil(view.image)
|
|
450
|
-
controller.view.addSubview(view)
|
|
451
|
-
eventually("Reattached view decodes") { view.image != nil }
|
|
452
|
-
icon.prepareForRecycle(); XCTAssertNil(view.image)
|
|
453
|
-
RunLoop.main.run(until: Date().addingTimeInterval(0.1)); XCTAssertNil(view.image)
|
|
454
|
-
icon.iconName = "BotIllus"; icon.resolvedColor = "rgba(255,0,0,1)"; icon.afterUpdate()
|
|
455
|
-
eventually("Reused view decodes") { view.image != nil }
|
|
456
|
-
icon.onDropView(); XCTAssertNil(view.image)
|
|
457
|
-
view.removeFromSuperview()
|
|
458
|
-
|
|
459
|
-
let names = ["GooglePayIllus", "ShortcutsCustom", "SidebarLeftArrowCustom", "PassKeySolid",
|
|
460
|
-
"ArrowTopRightIllus", "OnekeyTextIllus", "CheckboxCheckedCustom", "AppleBrand", "BotIllus",
|
|
461
|
-
"OnekeyPrimeLightColored", "OnekeyPrimeDarkColored", "ShieldDeviceDarkIllus", "CoinsIllus",
|
|
462
|
-
"MaticCircleIllus", "UserAvatarFallbackColored"]
|
|
463
|
-
var gallery: [HybridOneKeyIcon] = []
|
|
464
|
-
for (index, name) in names.enumerated() {
|
|
465
|
-
let hybrid = HybridOneKeyIcon()
|
|
466
|
-
hybrid.view.frame = CGRect(x: CGFloat(8 + (index % 3) * 128), y: CGFloat(60 + (index / 3) * 140), width: 112, height: 112)
|
|
467
|
-
controller.view.addSubview(hybrid.view)
|
|
468
|
-
hybrid.iconName = name; hybrid.resolvedColor = "rgba(255,0,0,0.5019607843137255)"; hybrid.afterUpdate()
|
|
469
|
-
gallery.append(hybrid)
|
|
470
|
-
}
|
|
471
|
-
eventually("All representative production views display") {
|
|
472
|
-
gallery.allSatisfy { ($0.view as? UIImageView)?.image != nil }
|
|
473
|
-
}
|
|
474
|
-
for (index, hybrid) in gallery.enumerated() {
|
|
475
|
-
try save(draw(try XCTUnwrap(hybrid.view as? UIImageView)), name: names[index] + ".svg")
|
|
476
|
-
}
|
|
477
|
-
let format = UIGraphicsImageRendererFormat(); format.scale = 1
|
|
478
|
-
let screenshot = UIGraphicsImageRenderer(bounds: controller.view.bounds, format: format).image { _ in
|
|
479
|
-
controller.view.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
|
|
480
|
-
}
|
|
481
|
-
try save(screenshot, name: "ios-production-gallery")
|
|
482
|
-
gallery.forEach { $0.onDropView() }
|
|
483
|
-
}
|
|
484
|
-
}
|
package/lib/module/icon/dom.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { iconResourceHref } from '#onekey-icon-assets';
|
|
4
|
-
|
|
5
|
-
/** Native SDK DOM consumers own name coverage, styling and accessible labels. */
|
|
6
|
-
export function createNamedIcon(document, name) {
|
|
7
|
-
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
8
|
-
svg.setAttribute('width', '24');
|
|
9
|
-
svg.setAttribute('height', '24');
|
|
10
|
-
svg.setAttribute('aria-hidden', 'true');
|
|
11
|
-
svg.setAttribute('focusable', 'false');
|
|
12
|
-
const href = iconResourceHref(name);
|
|
13
|
-
if (href) {
|
|
14
|
-
const use = document.createElementNS('http://www.w3.org/2000/svg', 'use');
|
|
15
|
-
use.setAttribute('href', href);
|
|
16
|
-
svg.append(use);
|
|
17
|
-
}
|
|
18
|
-
return svg;
|
|
19
|
-
}
|
|
20
|
-
/// <reference lib="dom" />
|
|
21
|
-
//# sourceMappingURL=dom.js.map
|
package/lib/module/icon/index.js
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { createElement } from 'react';
|
|
4
|
-
import { getHostComponent } from 'react-native-nitro-modules';
|
|
5
|
-
import { isIconName, normalizeIconColor } from "./props.js";
|
|
6
|
-
const config = require('../../nitrogen/generated/shared/json/OneKeyIconConfig.json');
|
|
7
|
-
const NativeIcon = getHostComponent('OneKeyIcon', () => config);
|
|
8
|
-
export function OneKeyIcon({
|
|
9
|
-
name,
|
|
10
|
-
color,
|
|
11
|
-
style,
|
|
12
|
-
...viewProps
|
|
13
|
-
}) {
|
|
14
|
-
const resolvedColor = normalizeIconColor(color);
|
|
15
|
-
if (__DEV__ && !resolvedColor) {
|
|
16
|
-
// Only hex, rgb() and rgba() are supported; anything else renders blank.
|
|
17
|
-
console.warn(`[OneKeyIcon] Unsupported color ${JSON.stringify(color)} for "${name}"; expected #hex, rgb() or rgba().`);
|
|
18
|
-
}
|
|
19
|
-
return /*#__PURE__*/createElement(NativeIcon, {
|
|
20
|
-
...viewProps,
|
|
21
|
-
iconName: resolvedColor && isIconName(name) ? name : '',
|
|
22
|
-
resolvedColor: resolvedColor ?? '',
|
|
23
|
-
style: [{
|
|
24
|
-
width: 24,
|
|
25
|
-
height: 24
|
|
26
|
-
}, style]
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { createElement } from 'react';
|
|
4
|
-
import { View } from 'react-native';
|
|
5
|
-
import { isIconName } from "./props.js";
|
|
6
|
-
import { iconResourceHref } from '#onekey-icon-assets';
|
|
7
|
-
export function OneKeyIcon({
|
|
8
|
-
name,
|
|
9
|
-
color,
|
|
10
|
-
style,
|
|
11
|
-
...viewProps
|
|
12
|
-
}) {
|
|
13
|
-
const defaultStyle = {
|
|
14
|
-
width: 24,
|
|
15
|
-
height: 24,
|
|
16
|
-
color: color ?? '#000000'
|
|
17
|
-
};
|
|
18
|
-
const href = isIconName(name) ? iconResourceHref(name) : undefined;
|
|
19
|
-
return /*#__PURE__*/createElement(View, {
|
|
20
|
-
...viewProps,
|
|
21
|
-
style: [defaultStyle, style]
|
|
22
|
-
}, href ? /*#__PURE__*/createElement('svg', {
|
|
23
|
-
'width': '100%',
|
|
24
|
-
'height': '100%',
|
|
25
|
-
'aria-hidden': true,
|
|
26
|
-
'focusable': false,
|
|
27
|
-
'children': /*#__PURE__*/createElement('use', {
|
|
28
|
-
href
|
|
29
|
-
})
|
|
30
|
-
}) : null);
|
|
31
|
-
}
|
|
32
|
-
//# sourceMappingURL=index.web.js.map
|
package/lib/module/icon/props.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
export function normalizeIconColor(input = '#000000') {
|
|
4
|
-
const hex = /^#([\da-f]{3}|[\da-f]{4}|[\da-f]{6}|[\da-f]{8})$/i.exec(input);
|
|
5
|
-
if (hex) {
|
|
6
|
-
let value = hex[1];
|
|
7
|
-
if (value.length < 5) value = [...value].map(part => part + part).join('');
|
|
8
|
-
const channels = [0, 2, 4].map(start => parseInt(value.slice(start, start + 2), 16));
|
|
9
|
-
const alpha = value.length === 8 ? parseInt(value.slice(6), 16) / 255 : 1;
|
|
10
|
-
return `rgba(${channels.join(',')},${alpha})`;
|
|
11
|
-
}
|
|
12
|
-
const rgb = /^(rgb|rgba)\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*((?:\d+(?:\.\d*)?|\.\d+))\s*)?\)$/.exec(input);
|
|
13
|
-
if (!rgb || rgb[1] === 'rgba' !== (rgb[5] !== undefined)) return undefined;
|
|
14
|
-
const channels = rgb.slice(2, 5).map(Number);
|
|
15
|
-
const alpha = Number(rgb[5] ?? 1);
|
|
16
|
-
if (channels.some(value => value > 255) || !Number.isFinite(alpha) || alpha > 1) return undefined;
|
|
17
|
-
return `rgba(${channels.join(',')},${Math.round(alpha * 255) / 255})`;
|
|
18
|
-
}
|
|
19
|
-
export function isIconName(name) {
|
|
20
|
-
return /^[A-Z][A-Za-z0-9]*$/.test(name);
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=props.js.map
|