@yeomessagingcom/react-native-yeofr 0.1.3
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 +9 -0
- package/index.ts +11 -0
- package/ios/YEOFRModule.m +36 -0
- package/ios/YEOFRModule.swift +86 -0
- package/ios/react-native-yeofr.podspec +38 -0
- package/package.json +29 -0
- package/react-native.config.js +11 -0
package/README.md
ADDED
package/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NativeModules } from 'react-native';
|
|
2
|
+
const { YEOFRModule } = NativeModules as any;
|
|
3
|
+
|
|
4
|
+
export const createTracker = (): Promise<number> => YEOFRModule.createTracker();
|
|
5
|
+
export const freeTracker = (): Promise<number> => YEOFRModule.freeTracker();
|
|
6
|
+
export const getTrackerData = (): Promise<string> => YEOFRModule.getTrackerData();
|
|
7
|
+
export const loadTracker = (base64: string): Promise<number> => YEOFRModule.loadTracker(base64);
|
|
8
|
+
export const enroll = (faceID: number, name: string): Promise<number> => YEOFRModule.enroll(faceID, name);
|
|
9
|
+
export const processFrameBase64 = (args: {
|
|
10
|
+
base64ARGB: string; width: number; height: number; stride: number; ratio?: number; needFaceRect?: boolean;
|
|
11
|
+
}) => YEOFRModule.processFrameBase64(args.base64ARGB, args.width, args.height, args.stride, args.ratio ?? 1, !!args.needFaceRect);
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_MODULE(YEOFRModule, NSObject)
|
|
4
|
+
|
|
5
|
+
RCT_EXTERN_METHOD(createTracker:(RCTPromiseResolveBlock)resolve
|
|
6
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
7
|
+
|
|
8
|
+
RCT_EXTERN_METHOD(freeTracker:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
10
|
+
|
|
11
|
+
RCT_EXTERN_METHOD(resetTrackerParameters:(NSString *)paramString
|
|
12
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
13
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
14
|
+
|
|
15
|
+
RCT_EXTERN_METHOD(getTrackerData:(RCTPromiseResolveBlock)resolve
|
|
16
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
17
|
+
|
|
18
|
+
RCT_EXTERN_METHOD(loadTracker:(NSString *)base64Blob
|
|
19
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
20
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
21
|
+
|
|
22
|
+
RCT_EXTERN_METHOD(enroll:(nonnull NSNumber *)faceID
|
|
23
|
+
name:(NSString *)name
|
|
24
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
25
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
26
|
+
|
|
27
|
+
RCT_EXTERN_METHOD(processFrameBase64:(NSString *)base64ARGB
|
|
28
|
+
width:(nonnull NSNumber *)width
|
|
29
|
+
height:(nonnull NSNumber *)height
|
|
30
|
+
stride:(nonnull NSNumber *)stride
|
|
31
|
+
ratio:(nonnull NSNumber *)ratio
|
|
32
|
+
needFaceRect:(BOOL)needFaceRect
|
|
33
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
34
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
35
|
+
|
|
36
|
+
@end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import YEOFRSDK // from your xcframework
|
|
3
|
+
|
|
4
|
+
@objc(YEOFRModule)
|
|
5
|
+
class YEOFRModule: NSObject {
|
|
6
|
+
private let sdk = YEOFRSDK.shared
|
|
7
|
+
@objc static func requiresMainQueueSetup() -> Bool { false }
|
|
8
|
+
|
|
9
|
+
@objc func createTracker(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
|
|
10
|
+
let rc = sdk.createTracker()
|
|
11
|
+
rc == .OK ? resolve(rc.rawValue) : reject("rc", "createTracker failed: \(rc.rawValue)", nil)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@objc func freeTracker(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
|
|
15
|
+
let rc = sdk.freeTracker()
|
|
16
|
+
rc == .OK ? resolve(rc.rawValue) : reject("rc", "freeTracker failed: \(rc.rawValue)", nil)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@objc func resetTrackerParameters(_ _: String,
|
|
20
|
+
resolver resolve: RCTPromiseResolveBlock,
|
|
21
|
+
rejecter reject: RCTPromiseRejectBlock) {
|
|
22
|
+
let rc = sdk.resetTrackerParameters()
|
|
23
|
+
rc == .OK ? resolve(rc.rawValue) : reject("rc", "resetTrackerParameters failed: \(rc.rawValue)", nil)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@objc func getTrackerData(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
|
|
27
|
+
guard let data = sdk.faceRecognitionTrackerData() else {
|
|
28
|
+
return reject("no_data", "tracker data unavailable", nil)
|
|
29
|
+
}
|
|
30
|
+
resolve(data.base64EncodedString())
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@objc func loadTracker(_ base64Blob: String,
|
|
34
|
+
resolver resolve: RCTPromiseResolveBlock,
|
|
35
|
+
rejecter reject: RCTPromiseRejectBlock) {
|
|
36
|
+
guard let d = Data(base64Encoded: base64Blob) else {
|
|
37
|
+
return reject("bad_input", "invalid base64", nil)
|
|
38
|
+
}
|
|
39
|
+
let rc = sdk.loadTracker(from: d)
|
|
40
|
+
rc == .OK ? resolve(rc.rawValue) : reject("rc", "loadTracker failed: \(rc.rawValue)", nil)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@objc func enroll(_ faceID: NSNumber,
|
|
44
|
+
name: String,
|
|
45
|
+
resolver resolve: RCTPromiseResolveBlock,
|
|
46
|
+
rejecter reject: RCTPromiseRejectBlock) {
|
|
47
|
+
let rc = sdk.enroll(faceID: faceID.int64Value, name: name, learnFromCurrentFrame: true)
|
|
48
|
+
rc == .OK ? resolve(rc.rawValue) : reject("rc", "enroll failed: \(rc.rawValue)", nil)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// JS-only helper for quick smoke tests; production should feed frames via native iOS component.
|
|
52
|
+
@objc func processFrameBase64(_ base64ARGB: String,
|
|
53
|
+
width: NSNumber,
|
|
54
|
+
height: NSNumber,
|
|
55
|
+
stride: NSNumber,
|
|
56
|
+
ratio: NSNumber,
|
|
57
|
+
needFaceRect: Bool,
|
|
58
|
+
resolver resolve: RCTPromiseResolveBlock,
|
|
59
|
+
rejecter reject: RCTPromiseRejectBlock) {
|
|
60
|
+
guard let bytes = Data(base64Encoded: base64ARGB) else {
|
|
61
|
+
return reject("bad_input", "invalid base64", nil)
|
|
62
|
+
}
|
|
63
|
+
let count = bytes.count
|
|
64
|
+
let ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: count)
|
|
65
|
+
_ = bytes.copyBytes(to: ptr, count: count)
|
|
66
|
+
|
|
67
|
+
let params = ImageFrameParameters(buffer: ptr,
|
|
68
|
+
width: width.intValue,
|
|
69
|
+
height: height.intValue,
|
|
70
|
+
scanLine: stride.intValue,
|
|
71
|
+
ratio: ratio.floatValue)
|
|
72
|
+
let result = sdk.detectFaces(params: params, needFaceRect: needFaceRect)
|
|
73
|
+
|
|
74
|
+
var faces: [[String: Any]] = []
|
|
75
|
+
if let rects = result.faceRects, let ids = result.faceIDs {
|
|
76
|
+
for (id, rect) in rects {
|
|
77
|
+
faces.append([
|
|
78
|
+
"id": id,
|
|
79
|
+
"name": ids[id] ?? NSNull(),
|
|
80
|
+
"rect": ["x": rect.origin.x, "y": rect.origin.y, "w": rect.size.width, "h": rect.size.height]
|
|
81
|
+
])
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
resolve(["state": result.faceState.rawValue, "count": result.detectedCount, "faces": faces])
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = "react-native-yeofr"
|
|
3
|
+
s.version = "0.1.3" # keep in lockstep with npm + SPM release tag
|
|
4
|
+
s.summary = "React Native iOS integration for YEO Face Recognition (device-only)."
|
|
5
|
+
s.homepage = "https://github.com/yeomessaging/react-native-yeofr"
|
|
6
|
+
s.license = { :type => "Commercial", :file => "../LICENSE" }
|
|
7
|
+
s.author = { "YEO Messaging" => "luca@yeomessaging.com" }
|
|
8
|
+
s.platform = :ios, "15.0"
|
|
9
|
+
s.swift_version = "5.9"
|
|
10
|
+
|
|
11
|
+
# Only the RN shim files (bridges are inside your xcframework)
|
|
12
|
+
s.source_files = "YEOFRModule.m", "YEOFRModule.swift"
|
|
13
|
+
|
|
14
|
+
# Download the binary zip from your SPM repo release assets
|
|
15
|
+
repo = "https://github.com/YEOMessaging/YEOFR-SPM"
|
|
16
|
+
zip = "YEOFR.xcframework.zip"
|
|
17
|
+
url = ENV['YEOFR_XCFRAMEWORK_URL'] || "#{repo}/releases/download/#{s.version}/#{zip}"
|
|
18
|
+
s.source = { :http => url }
|
|
19
|
+
# Optionally verify integrity:
|
|
20
|
+
# s.source = { :http => url, :sha256 => "PUT_SHA256_HERE" }
|
|
21
|
+
|
|
22
|
+
s.prepare_command = <<-CMD
|
|
23
|
+
rm -rf Vendor && mkdir -p Vendor
|
|
24
|
+
unzip -o #{zip} -d Vendor >/dev/null
|
|
25
|
+
CMD
|
|
26
|
+
|
|
27
|
+
s.vendored_frameworks = "Vendor/YEOFR.xcframework"
|
|
28
|
+
s.dependency "React-Core"
|
|
29
|
+
|
|
30
|
+
# Device-only: exclude simulator archs
|
|
31
|
+
s.pod_target_xcconfig = {
|
|
32
|
+
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386 x86_64 arm64',
|
|
33
|
+
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES'
|
|
34
|
+
}
|
|
35
|
+
s.user_target_xcconfig = {
|
|
36
|
+
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386 x86_64 arm64'
|
|
37
|
+
}
|
|
38
|
+
end
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yeomessagingcom/react-native-yeofr",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "React Native iOS integration for YEO Face Recognition (device-only).",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"react-native": "index.ts",
|
|
7
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
8
|
+
"author": "YEO Messaging",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/yeomessaging/react-native-yeofr.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/YEOMessaging/react-native-yeofr#readme",
|
|
14
|
+
"bugs": { "email": "luca@yeomessaging.com", "url": "https://github.com/YEOMessaging/react-native-yeofr/issues" },
|
|
15
|
+
"files": [
|
|
16
|
+
"index.ts",
|
|
17
|
+
"ios",
|
|
18
|
+
"react-native.config.js",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"keywords": ["react-native", "ios", "face-recognition", "yeofr"],
|
|
23
|
+
"peerDependencies": {
|
|
24
|
+
"react-native": ">=0.72.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/react-native": "^0.72.0"
|
|
28
|
+
}
|
|
29
|
+
}
|