@arfuhad/react-native-smart-camera 0.1.0
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/ARCHITECTURE.md +341 -0
- package/README.md +154 -0
- package/android/build.gradle +89 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/expo/modules/smartcamera/ImageLoader.kt +106 -0
- package/android/src/main/java/expo/modules/smartcamera/MLKitFaceDetector.kt +273 -0
- package/android/src/main/java/expo/modules/smartcamera/SmartCameraModule.kt +205 -0
- package/android/src/main/java/expo/modules/smartcamera/SmartCameraView.kt +153 -0
- package/android/src/main/java/expo/modules/smartcamera/WebRTCFrameBridge.kt +184 -0
- package/app.plugin.js +17 -0
- package/build/SmartCamera.d.ts +17 -0
- package/build/SmartCamera.d.ts.map +1 -0
- package/build/SmartCamera.js +270 -0
- package/build/SmartCamera.js.map +1 -0
- package/build/SmartCameraModule.d.ts +112 -0
- package/build/SmartCameraModule.d.ts.map +1 -0
- package/build/SmartCameraModule.js +121 -0
- package/build/SmartCameraModule.js.map +1 -0
- package/build/SmartCameraView.d.ts +8 -0
- package/build/SmartCameraView.d.ts.map +1 -0
- package/build/SmartCameraView.js +7 -0
- package/build/SmartCameraView.js.map +1 -0
- package/build/detection/blinkProcessor.d.ts +23 -0
- package/build/detection/blinkProcessor.d.ts.map +1 -0
- package/build/detection/blinkProcessor.js +90 -0
- package/build/detection/blinkProcessor.js.map +1 -0
- package/build/detection/faceDetector.d.ts +16 -0
- package/build/detection/faceDetector.d.ts.map +1 -0
- package/build/detection/faceDetector.js +46 -0
- package/build/detection/faceDetector.js.map +1 -0
- package/build/detection/index.d.ts +4 -0
- package/build/detection/index.d.ts.map +1 -0
- package/build/detection/index.js +4 -0
- package/build/detection/index.js.map +1 -0
- package/build/detection/staticImageDetector.d.ts +25 -0
- package/build/detection/staticImageDetector.d.ts.map +1 -0
- package/build/detection/staticImageDetector.js +48 -0
- package/build/detection/staticImageDetector.js.map +1 -0
- package/build/hooks/index.d.ts +5 -0
- package/build/hooks/index.d.ts.map +1 -0
- package/build/hooks/index.js +5 -0
- package/build/hooks/index.js.map +1 -0
- package/build/hooks/useBlinkDetection.d.ts +39 -0
- package/build/hooks/useBlinkDetection.d.ts.map +1 -0
- package/build/hooks/useBlinkDetection.js +67 -0
- package/build/hooks/useBlinkDetection.js.map +1 -0
- package/build/hooks/useFaceDetection.d.ts +46 -0
- package/build/hooks/useFaceDetection.d.ts.map +1 -0
- package/build/hooks/useFaceDetection.js +80 -0
- package/build/hooks/useFaceDetection.js.map +1 -0
- package/build/hooks/useSmartCamera.d.ts +31 -0
- package/build/hooks/useSmartCamera.d.ts.map +1 -0
- package/build/hooks/useSmartCamera.js +75 -0
- package/build/hooks/useSmartCamera.js.map +1 -0
- package/build/hooks/useSmartCameraWebRTC.d.ts +58 -0
- package/build/hooks/useSmartCameraWebRTC.d.ts.map +1 -0
- package/build/hooks/useSmartCameraWebRTC.js +160 -0
- package/build/hooks/useSmartCameraWebRTC.js.map +1 -0
- package/build/index.d.ts +14 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +20 -0
- package/build/index.js.map +1 -0
- package/build/types.d.ts +478 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/utils/index.d.ts +98 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +276 -0
- package/build/utils/index.js.map +1 -0
- package/build/webrtc/WebRTCBridge.d.ts +55 -0
- package/build/webrtc/WebRTCBridge.d.ts.map +1 -0
- package/build/webrtc/WebRTCBridge.js +113 -0
- package/build/webrtc/WebRTCBridge.js.map +1 -0
- package/build/webrtc/index.d.ts +3 -0
- package/build/webrtc/index.d.ts.map +1 -0
- package/build/webrtc/index.js +2 -0
- package/build/webrtc/index.js.map +1 -0
- package/build/webrtc/types.d.ts +64 -0
- package/build/webrtc/types.d.ts.map +1 -0
- package/build/webrtc/types.js +5 -0
- package/build/webrtc/types.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/MLKitFaceDetector.swift +310 -0
- package/ios/SmartCamera.podspec +33 -0
- package/ios/SmartCameraModule.swift +225 -0
- package/ios/SmartCameraView.swift +146 -0
- package/ios/WebRTCFrameBridge.swift +150 -0
- package/package.json +91 -0
- package/plugin/build/index.d.ts +28 -0
- package/plugin/build/index.js +33 -0
- package/plugin/build/withSmartCameraAndroid.d.ts +9 -0
- package/plugin/build/withSmartCameraAndroid.js +108 -0
- package/plugin/build/withSmartCameraIOS.d.ts +11 -0
- package/plugin/build/withSmartCameraIOS.js +92 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import UIKit
|
|
3
|
+
import AVFoundation
|
|
4
|
+
|
|
5
|
+
class SmartCameraView: ExpoView {
|
|
6
|
+
// MARK: - Properties
|
|
7
|
+
|
|
8
|
+
var cameraFacing: AVCaptureDevice.Position = .front {
|
|
9
|
+
didSet {
|
|
10
|
+
if cameraFacing != oldValue {
|
|
11
|
+
setupCamera()
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
var isActive: Bool = true {
|
|
17
|
+
didSet {
|
|
18
|
+
if isActive != oldValue {
|
|
19
|
+
updateCameraState()
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private var captureSession: AVCaptureSession?
|
|
25
|
+
private var previewLayer: AVCaptureVideoPreviewLayer?
|
|
26
|
+
private var videoOutput: AVCaptureVideoDataOutput?
|
|
27
|
+
|
|
28
|
+
// MARK: - Initialization
|
|
29
|
+
|
|
30
|
+
required init(appContext: AppContext? = nil) {
|
|
31
|
+
super.init(appContext: appContext)
|
|
32
|
+
setupView()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// MARK: - Setup
|
|
36
|
+
|
|
37
|
+
private func setupView() {
|
|
38
|
+
backgroundColor = .black
|
|
39
|
+
clipsToBounds = true
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private func setupCamera() {
|
|
43
|
+
// Remove existing session
|
|
44
|
+
captureSession?.stopRunning()
|
|
45
|
+
previewLayer?.removeFromSuperlayer()
|
|
46
|
+
|
|
47
|
+
// Create new session
|
|
48
|
+
let session = AVCaptureSession()
|
|
49
|
+
session.sessionPreset = .high
|
|
50
|
+
|
|
51
|
+
// Get camera device
|
|
52
|
+
guard let device = getCameraDevice() else {
|
|
53
|
+
print("[SmartCameraView] No camera device available")
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
do {
|
|
58
|
+
let input = try AVCaptureDeviceInput(device: device)
|
|
59
|
+
|
|
60
|
+
if session.canAddInput(input) {
|
|
61
|
+
session.addInput(input)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add video output
|
|
65
|
+
let output = AVCaptureVideoDataOutput()
|
|
66
|
+
output.videoSettings = [
|
|
67
|
+
kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA
|
|
68
|
+
]
|
|
69
|
+
output.alwaysDiscardsLateVideoFrames = true
|
|
70
|
+
|
|
71
|
+
if session.canAddOutput(output) {
|
|
72
|
+
session.addOutput(output)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
videoOutput = output
|
|
76
|
+
|
|
77
|
+
// Setup preview layer
|
|
78
|
+
let preview = AVCaptureVideoPreviewLayer(session: session)
|
|
79
|
+
preview.videoGravity = .resizeAspectFill
|
|
80
|
+
preview.frame = bounds
|
|
81
|
+
layer.addSublayer(preview)
|
|
82
|
+
|
|
83
|
+
previewLayer = preview
|
|
84
|
+
captureSession = session
|
|
85
|
+
|
|
86
|
+
// Start session on background thread
|
|
87
|
+
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
88
|
+
self?.captureSession?.startRunning()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
} catch {
|
|
92
|
+
print("[SmartCameraView] Error setting up camera: \(error)")
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private func getCameraDevice() -> AVCaptureDevice? {
|
|
97
|
+
let deviceTypes: [AVCaptureDevice.DeviceType] = [
|
|
98
|
+
.builtInWideAngleCamera,
|
|
99
|
+
.builtInDualCamera,
|
|
100
|
+
.builtInTrueDepthCamera
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
let discoverySession = AVCaptureDevice.DiscoverySession(
|
|
104
|
+
deviceTypes: deviceTypes,
|
|
105
|
+
mediaType: .video,
|
|
106
|
+
position: cameraFacing
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return discoverySession.devices.first
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private func updateCameraState() {
|
|
113
|
+
if isActive {
|
|
114
|
+
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
115
|
+
self?.captureSession?.startRunning()
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
119
|
+
self?.captureSession?.stopRunning()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// MARK: - Layout
|
|
125
|
+
|
|
126
|
+
override func layoutSubviews() {
|
|
127
|
+
super.layoutSubviews()
|
|
128
|
+
previewLayer?.frame = bounds
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// MARK: - Lifecycle
|
|
132
|
+
|
|
133
|
+
override func didMoveToWindow() {
|
|
134
|
+
super.didMoveToWindow()
|
|
135
|
+
if window != nil && captureSession == nil {
|
|
136
|
+
setupCamera()
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
override func removeFromSuperview() {
|
|
141
|
+
captureSession?.stopRunning()
|
|
142
|
+
captureSession = nil
|
|
143
|
+
super.removeFromSuperview()
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import AVFoundation
|
|
3
|
+
|
|
4
|
+
// Note: This is a placeholder implementation.
|
|
5
|
+
// In production, you would integrate with WebRTC.framework
|
|
6
|
+
// and react-native-webrtc's RTCVideoSource.
|
|
7
|
+
|
|
8
|
+
class WebRTCFrameBridge {
|
|
9
|
+
// MARK: - Properties
|
|
10
|
+
|
|
11
|
+
private var isInitialized = false
|
|
12
|
+
private var isStreaming = false
|
|
13
|
+
private var streamWidth: Int = 1280
|
|
14
|
+
private var streamHeight: Int = 720
|
|
15
|
+
private var streamFrameRate: Int = 30
|
|
16
|
+
|
|
17
|
+
private var frameQueue: DispatchQueue?
|
|
18
|
+
private var lastFrameTime: CFTimeInterval = 0
|
|
19
|
+
private var frameInterval: CFTimeInterval = 1.0 / 30.0
|
|
20
|
+
|
|
21
|
+
// MARK: - Initialization
|
|
22
|
+
|
|
23
|
+
func initialize() async throws {
|
|
24
|
+
guard !isInitialized else { return }
|
|
25
|
+
|
|
26
|
+
// Initialize WebRTC
|
|
27
|
+
// In production: RTCInitializeSSL()
|
|
28
|
+
|
|
29
|
+
frameQueue = DispatchQueue(label: "com.smartcamera.webrtc.frame", qos: .userInteractive)
|
|
30
|
+
isInitialized = true
|
|
31
|
+
|
|
32
|
+
print("[WebRTCFrameBridge] Initialized")
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// MARK: - Streaming
|
|
36
|
+
|
|
37
|
+
func startStream(width: Int, height: Int, frameRate: Int) async throws {
|
|
38
|
+
guard isInitialized else {
|
|
39
|
+
throw NSError(domain: "WebRTCFrameBridge", code: 1, userInfo: [
|
|
40
|
+
NSLocalizedDescriptionKey: "WebRTC not initialized"
|
|
41
|
+
])
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
guard !isStreaming else {
|
|
45
|
+
print("[WebRTCFrameBridge] Already streaming")
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
streamWidth = width
|
|
50
|
+
streamHeight = height
|
|
51
|
+
streamFrameRate = frameRate
|
|
52
|
+
frameInterval = 1.0 / Double(frameRate)
|
|
53
|
+
|
|
54
|
+
// In production:
|
|
55
|
+
// 1. Create RTCVideoSource
|
|
56
|
+
// 2. Create RTCVideoTrack
|
|
57
|
+
// 3. Add track to peer connection
|
|
58
|
+
|
|
59
|
+
isStreaming = true
|
|
60
|
+
print("[WebRTCFrameBridge] Started streaming: \(width)x\(height)@\(frameRate)fps")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func stopStream() async {
|
|
64
|
+
guard isStreaming else { return }
|
|
65
|
+
|
|
66
|
+
// In production:
|
|
67
|
+
// 1. Remove track from peer connection
|
|
68
|
+
// 2. Stop video source
|
|
69
|
+
|
|
70
|
+
isStreaming = false
|
|
71
|
+
print("[WebRTCFrameBridge] Stopped streaming")
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// MARK: - Frame Processing
|
|
75
|
+
|
|
76
|
+
func pushFrame(_ frameData: [String: Any]) {
|
|
77
|
+
guard isStreaming else { return }
|
|
78
|
+
|
|
79
|
+
// Rate limiting
|
|
80
|
+
let currentTime = CACurrentMediaTime()
|
|
81
|
+
guard currentTime - lastFrameTime >= frameInterval else { return }
|
|
82
|
+
lastFrameTime = currentTime
|
|
83
|
+
|
|
84
|
+
frameQueue?.async { [weak self] in
|
|
85
|
+
self?.processFrame(frameData)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
func pushSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
|
|
90
|
+
guard isStreaming else { return }
|
|
91
|
+
|
|
92
|
+
// Rate limiting
|
|
93
|
+
let currentTime = CACurrentMediaTime()
|
|
94
|
+
guard currentTime - lastFrameTime >= frameInterval else { return }
|
|
95
|
+
lastFrameTime = currentTime
|
|
96
|
+
|
|
97
|
+
frameQueue?.async { [weak self] in
|
|
98
|
+
self?.processSampleBuffer(sampleBuffer)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private func processFrame(_ frameData: [String: Any]) {
|
|
103
|
+
// In production:
|
|
104
|
+
// 1. Convert frame data to RTCVideoFrame
|
|
105
|
+
// 2. Push to RTCVideoSource
|
|
106
|
+
|
|
107
|
+
// Placeholder - log frame info
|
|
108
|
+
if let width = frameData["width"], let height = frameData["height"] {
|
|
109
|
+
// print("[WebRTCFrameBridge] Processing frame: \(width)x\(height)")
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private func processSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
|
|
114
|
+
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// In production:
|
|
119
|
+
// 1. Convert CVPixelBuffer to RTCCVPixelBuffer
|
|
120
|
+
// 2. Create RTCVideoFrame
|
|
121
|
+
// 3. Push to RTCVideoSource
|
|
122
|
+
|
|
123
|
+
// Example conversion (pseudo-code):
|
|
124
|
+
/*
|
|
125
|
+
let rtcPixelBuffer = RTCCVPixelBuffer(pixelBuffer: pixelBuffer)
|
|
126
|
+
let timeStampNs = Int64(CACurrentMediaTime() * 1_000_000_000)
|
|
127
|
+
let rotation = RTCVideoRotation._0
|
|
128
|
+
|
|
129
|
+
let frame = RTCVideoFrame(
|
|
130
|
+
buffer: rtcPixelBuffer,
|
|
131
|
+
rotation: rotation,
|
|
132
|
+
timeStampNs: timeStampNs
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
videoSource?.capturer(self, didCapture: frame)
|
|
136
|
+
*/
|
|
137
|
+
|
|
138
|
+
let width = CVPixelBufferGetWidth(pixelBuffer)
|
|
139
|
+
let height = CVPixelBufferGetHeight(pixelBuffer)
|
|
140
|
+
// print("[WebRTCFrameBridge] Processing sample buffer: \(width)x\(height)")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// MARK: - Utilities
|
|
144
|
+
|
|
145
|
+
var currentStreamConfig: (width: Int, height: Int, frameRate: Int)? {
|
|
146
|
+
guard isStreaming else { return nil }
|
|
147
|
+
return (streamWidth, streamHeight, streamFrameRate)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arfuhad/react-native-smart-camera",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Expo-compatible native module for camera preview, face detection, blink detection, and WebRTC streaming",
|
|
5
|
+
"main": "build/index.js",
|
|
6
|
+
"types": "build/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "expo-module build",
|
|
9
|
+
"build:plugin": "tsc --project plugin/tsconfig.json",
|
|
10
|
+
"clean": "expo-module clean && rm -rf plugin/build",
|
|
11
|
+
"lint": "expo-module lint",
|
|
12
|
+
"test": "expo-module test",
|
|
13
|
+
"prepare": "expo-module prepare && npm run build:plugin",
|
|
14
|
+
"prepublishOnly": "expo-module prepublishOnly",
|
|
15
|
+
"expo-module": "expo-module"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"react-native",
|
|
19
|
+
"expo",
|
|
20
|
+
"camera",
|
|
21
|
+
"face-detection",
|
|
22
|
+
"blink-detection",
|
|
23
|
+
"webrtc",
|
|
24
|
+
"vision-camera",
|
|
25
|
+
"ml-kit",
|
|
26
|
+
"expo-module",
|
|
27
|
+
"frame-processor"
|
|
28
|
+
],
|
|
29
|
+
"files": [
|
|
30
|
+
"build",
|
|
31
|
+
"ios",
|
|
32
|
+
"android",
|
|
33
|
+
"plugin/build",
|
|
34
|
+
"app.plugin.js",
|
|
35
|
+
"expo-module.config.json",
|
|
36
|
+
"README.md",
|
|
37
|
+
"ARCHITECTURE.md"
|
|
38
|
+
],
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/arfuhad/react-native-smart-camera.git"
|
|
42
|
+
},
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/arfuhad/react-native-smart-camera/issues"
|
|
45
|
+
},
|
|
46
|
+
"author": "arfuhad",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"homepage": "https://github.com/arfuhad/react-native-smart-camera#readme",
|
|
49
|
+
"exports": {
|
|
50
|
+
".": {
|
|
51
|
+
"types": "./build/index.d.ts",
|
|
52
|
+
"default": "./build/index.js"
|
|
53
|
+
},
|
|
54
|
+
"./plugin": {
|
|
55
|
+
"types": "./plugin/build/index.d.ts",
|
|
56
|
+
"default": "./plugin/build/index.js"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"expo": ">=49.0.0",
|
|
61
|
+
"react": ">=18.0.0",
|
|
62
|
+
"react-native": ">=0.72.0",
|
|
63
|
+
"react-native-vision-camera": ">=3.0.0",
|
|
64
|
+
"react-native-webrtc": ">=118.0.0",
|
|
65
|
+
"react-native-worklets-core": ">=1.0.0"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@expo/config-plugins": "^7.8.0",
|
|
69
|
+
"@types/react": "^18.2.0",
|
|
70
|
+
"expo": "^51.0.0",
|
|
71
|
+
"expo-module-scripts": "^3.4.1",
|
|
72
|
+
"expo-modules-core": "^1.11.0",
|
|
73
|
+
"react": "^18.2.0",
|
|
74
|
+
"react-native": "^0.74.0",
|
|
75
|
+
"react-native-vision-camera": "^4.0.0",
|
|
76
|
+
"react-native-webrtc": "^118.0.7",
|
|
77
|
+
"react-native-worklets-core": "^1.3.0",
|
|
78
|
+
"typescript": "^5.3.0"
|
|
79
|
+
},
|
|
80
|
+
"peerDependenciesMeta": {
|
|
81
|
+
"react-native-vision-camera": {
|
|
82
|
+
"optional": false
|
|
83
|
+
},
|
|
84
|
+
"react-native-webrtc": {
|
|
85
|
+
"optional": true
|
|
86
|
+
},
|
|
87
|
+
"react-native-worklets-core": {
|
|
88
|
+
"optional": false
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
/**
|
|
3
|
+
* Plugin options for react-native-smart-camera
|
|
4
|
+
*/
|
|
5
|
+
export interface SmartCameraPluginOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Custom camera usage description for iOS
|
|
8
|
+
* @default "This app uses the camera for face detection and video streaming"
|
|
9
|
+
*/
|
|
10
|
+
cameraPermissionText?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Custom microphone usage description for iOS
|
|
13
|
+
* @default "This app uses the microphone for audio streaming"
|
|
14
|
+
*/
|
|
15
|
+
microphonePermissionText?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Enable ML Kit Face Detection
|
|
18
|
+
* @default true
|
|
19
|
+
*/
|
|
20
|
+
enableMLKit?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Enable WebRTC support
|
|
23
|
+
* @default true
|
|
24
|
+
*/
|
|
25
|
+
enableWebRTC?: boolean;
|
|
26
|
+
}
|
|
27
|
+
declare const _default: ConfigPlugin<void | SmartCameraPluginOptions>;
|
|
28
|
+
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
4
|
+
const withSmartCameraIOS_1 = require("./withSmartCameraIOS");
|
|
5
|
+
const withSmartCameraAndroid_1 = require("./withSmartCameraAndroid");
|
|
6
|
+
const pkg = require('../../package.json');
|
|
7
|
+
/**
|
|
8
|
+
* Expo config plugin for react-native-smart-camera
|
|
9
|
+
*
|
|
10
|
+
* This plugin:
|
|
11
|
+
* - Adds camera and microphone permissions
|
|
12
|
+
* - Configures iOS frameworks
|
|
13
|
+
* - Sets up Android Proguard rules
|
|
14
|
+
* - Adds ML Kit dependencies
|
|
15
|
+
*/
|
|
16
|
+
const withSmartCamera = (config, options = {}) => {
|
|
17
|
+
const { cameraPermissionText = 'This app uses the camera for face detection and video streaming', microphonePermissionText = 'This app uses the microphone for audio streaming', enableMLKit = true, enableWebRTC = true, } = options ?? {};
|
|
18
|
+
// Apply iOS configuration
|
|
19
|
+
config = (0, withSmartCameraIOS_1.withSmartCameraIOS)(config, {
|
|
20
|
+
cameraPermissionText,
|
|
21
|
+
microphonePermissionText,
|
|
22
|
+
enableMLKit,
|
|
23
|
+
enableWebRTC,
|
|
24
|
+
});
|
|
25
|
+
// Apply Android configuration
|
|
26
|
+
config = (0, withSmartCameraAndroid_1.withSmartCameraAndroid)(config, {
|
|
27
|
+
enableMLKit,
|
|
28
|
+
enableWebRTC,
|
|
29
|
+
});
|
|
30
|
+
return config;
|
|
31
|
+
};
|
|
32
|
+
exports.default = (0, config_plugins_1.createRunOncePlugin)(withSmartCamera, pkg.name, pkg.version);
|
|
33
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSx5REFBeUU7QUFDekUsNkRBQTBEO0FBQzFELHFFQUFrRTtBQUVsRSxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQztBQStCMUM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLGVBQWUsR0FBa0QsQ0FBQyxNQUFNLEVBQUUsT0FBTyxHQUFHLEVBQUUsRUFBRSxFQUFFO0lBQzlGLE1BQU0sRUFDSixvQkFBb0IsR0FBRyxpRUFBaUUsRUFDeEYsd0JBQXdCLEdBQUcsa0RBQWtELEVBQzdFLFdBQVcsR0FBRyxJQUFJLEVBQ2xCLFlBQVksR0FBRyxJQUFJLEdBQ3BCLEdBQUcsT0FBTyxJQUFJLEVBQUUsQ0FBQztJQUVsQiwwQkFBMEI7SUFDMUIsTUFBTSxHQUFHLElBQUEsdUNBQWtCLEVBQUMsTUFBTSxFQUFFO1FBQ2xDLG9CQUFvQjtRQUNwQix3QkFBd0I7UUFDeEIsV0FBVztRQUNYLFlBQVk7S0FDYixDQUFDLENBQUM7SUFFSCw4QkFBOEI7SUFDOUIsTUFBTSxHQUFHLElBQUEsK0NBQXNCLEVBQUMsTUFBTSxFQUFFO1FBQ3RDLFdBQVc7UUFDWCxZQUFZO0tBQ2IsQ0FBQyxDQUFDO0lBRUgsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQyxDQUFDO0FBRUYsa0JBQWUsSUFBQSxvQ0FBbUIsRUFBQyxlQUFlLEVBQUUsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25maWdQbHVnaW4sIGNyZWF0ZVJ1bk9uY2VQbHVnaW4gfSBmcm9tICdAZXhwby9jb25maWctcGx1Z2lucyc7XG5pbXBvcnQgeyB3aXRoU21hcnRDYW1lcmFJT1MgfSBmcm9tICcuL3dpdGhTbWFydENhbWVyYUlPUyc7XG5pbXBvcnQgeyB3aXRoU21hcnRDYW1lcmFBbmRyb2lkIH0gZnJvbSAnLi93aXRoU21hcnRDYW1lcmFBbmRyb2lkJztcblxuY29uc3QgcGtnID0gcmVxdWlyZSgnLi4vLi4vcGFja2FnZS5qc29uJyk7XG5cbi8qKlxuICogUGx1Z2luIG9wdGlvbnMgZm9yIHJlYWN0LW5hdGl2ZS1zbWFydC1jYW1lcmFcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTbWFydENhbWVyYVBsdWdpbk9wdGlvbnMge1xuICAvKipcbiAgICogQ3VzdG9tIGNhbWVyYSB1c2FnZSBkZXNjcmlwdGlvbiBmb3IgaU9TXG4gICAqIEBkZWZhdWx0IFwiVGhpcyBhcHAgdXNlcyB0aGUgY2FtZXJhIGZvciBmYWNlIGRldGVjdGlvbiBhbmQgdmlkZW8gc3RyZWFtaW5nXCJcbiAgICovXG4gIGNhbWVyYVBlcm1pc3Npb25UZXh0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gbWljcm9waG9uZSB1c2FnZSBkZXNjcmlwdGlvbiBmb3IgaU9TXG4gICAqIEBkZWZhdWx0IFwiVGhpcyBhcHAgdXNlcyB0aGUgbWljcm9waG9uZSBmb3IgYXVkaW8gc3RyZWFtaW5nXCJcbiAgICovXG4gIG1pY3JvcGhvbmVQZXJtaXNzaW9uVGV4dD86IHN0cmluZztcblxuICAvKipcbiAgICogRW5hYmxlIE1MIEtpdCBGYWNlIERldGVjdGlvblxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICBlbmFibGVNTEtpdD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBXZWJSVEMgc3VwcG9ydFxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICBlbmFibGVXZWJSVEM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEV4cG8gY29uZmlnIHBsdWdpbiBmb3IgcmVhY3QtbmF0aXZlLXNtYXJ0LWNhbWVyYVxuICogXG4gKiBUaGlzIHBsdWdpbjpcbiAqIC0gQWRkcyBjYW1lcmEgYW5kIG1pY3JvcGhvbmUgcGVybWlzc2lvbnNcbiAqIC0gQ29uZmlndXJlcyBpT1MgZnJhbWV3b3Jrc1xuICogLSBTZXRzIHVwIEFuZHJvaWQgUHJvZ3VhcmQgcnVsZXNcbiAqIC0gQWRkcyBNTCBLaXQgZGVwZW5kZW5jaWVzXG4gKi9cbmNvbnN0IHdpdGhTbWFydENhbWVyYTogQ29uZmlnUGx1Z2luPFNtYXJ0Q2FtZXJhUGx1Z2luT3B0aW9ucyB8IHZvaWQ+ID0gKGNvbmZpZywgb3B0aW9ucyA9IHt9KSA9PiB7XG4gIGNvbnN0IHtcbiAgICBjYW1lcmFQZXJtaXNzaW9uVGV4dCA9ICdUaGlzIGFwcCB1c2VzIHRoZSBjYW1lcmEgZm9yIGZhY2UgZGV0ZWN0aW9uIGFuZCB2aWRlbyBzdHJlYW1pbmcnLFxuICAgIG1pY3JvcGhvbmVQZXJtaXNzaW9uVGV4dCA9ICdUaGlzIGFwcCB1c2VzIHRoZSBtaWNyb3Bob25lIGZvciBhdWRpbyBzdHJlYW1pbmcnLFxuICAgIGVuYWJsZU1MS2l0ID0gdHJ1ZSxcbiAgICBlbmFibGVXZWJSVEMgPSB0cnVlLFxuICB9ID0gb3B0aW9ucyA/PyB7fTtcblxuICAvLyBBcHBseSBpT1MgY29uZmlndXJhdGlvblxuICBjb25maWcgPSB3aXRoU21hcnRDYW1lcmFJT1MoY29uZmlnLCB7XG4gICAgY2FtZXJhUGVybWlzc2lvblRleHQsXG4gICAgbWljcm9waG9uZVBlcm1pc3Npb25UZXh0LFxuICAgIGVuYWJsZU1MS2l0LFxuICAgIGVuYWJsZVdlYlJUQyxcbiAgfSk7XG5cbiAgLy8gQXBwbHkgQW5kcm9pZCBjb25maWd1cmF0aW9uXG4gIGNvbmZpZyA9IHdpdGhTbWFydENhbWVyYUFuZHJvaWQoY29uZmlnLCB7XG4gICAgZW5hYmxlTUxLaXQsXG4gICAgZW5hYmxlV2ViUlRDLFxuICB9KTtcblxuICByZXR1cm4gY29uZmlnO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgY3JlYXRlUnVuT25jZVBsdWdpbih3aXRoU21hcnRDYW1lcmEsIHBrZy5uYW1lLCBwa2cudmVyc2lvbik7XG5cbiJdfQ==
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
export interface AndroidPluginOptions {
|
|
3
|
+
enableMLKit: boolean;
|
|
4
|
+
enableWebRTC: boolean;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Android configuration for react-native-smart-camera
|
|
8
|
+
*/
|
|
9
|
+
export declare const withSmartCameraAndroid: ConfigPlugin<AndroidPluginOptions>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.withSmartCameraAndroid = void 0;
|
|
4
|
+
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
+
/**
|
|
6
|
+
* Add camera and microphone permissions to AndroidManifest.xml
|
|
7
|
+
*/
|
|
8
|
+
const withPermissions = (config, _options) => {
|
|
9
|
+
return (0, config_plugins_1.withAndroidManifest)(config, (config) => {
|
|
10
|
+
const manifest = config.modResults;
|
|
11
|
+
// Ensure permissions array exists
|
|
12
|
+
if (!manifest.manifest['uses-permission']) {
|
|
13
|
+
manifest.manifest['uses-permission'] = [];
|
|
14
|
+
}
|
|
15
|
+
const permissions = manifest.manifest['uses-permission'];
|
|
16
|
+
// Camera permission
|
|
17
|
+
const cameraPermission = 'android.permission.CAMERA';
|
|
18
|
+
if (!permissions.some((p) => p.$?.['android:name'] === cameraPermission)) {
|
|
19
|
+
permissions.push({
|
|
20
|
+
$: { 'android:name': cameraPermission },
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Microphone permission
|
|
24
|
+
const micPermission = 'android.permission.RECORD_AUDIO';
|
|
25
|
+
if (!permissions.some((p) => p.$?.['android:name'] === micPermission)) {
|
|
26
|
+
permissions.push({
|
|
27
|
+
$: { 'android:name': micPermission },
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// Camera hardware feature
|
|
31
|
+
if (!manifest.manifest['uses-feature']) {
|
|
32
|
+
manifest.manifest['uses-feature'] = [];
|
|
33
|
+
}
|
|
34
|
+
const features = manifest.manifest['uses-feature'];
|
|
35
|
+
const cameraFeature = 'android.hardware.camera';
|
|
36
|
+
if (!features.some((f) => f.$?.['android:name'] === cameraFeature)) {
|
|
37
|
+
features.push({
|
|
38
|
+
$: {
|
|
39
|
+
'android:name': cameraFeature,
|
|
40
|
+
'android:required': 'false',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const cameraAutoFocus = 'android.hardware.camera.autofocus';
|
|
45
|
+
if (!features.some((f) => f.$?.['android:name'] === cameraAutoFocus)) {
|
|
46
|
+
features.push({
|
|
47
|
+
$: {
|
|
48
|
+
'android:name': cameraAutoFocus,
|
|
49
|
+
'android:required': 'false',
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return config;
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Add ML Kit dependency to app build.gradle
|
|
58
|
+
*/
|
|
59
|
+
const withMLKitDependency = (config, options) => {
|
|
60
|
+
if (!options.enableMLKit) {
|
|
61
|
+
return config;
|
|
62
|
+
}
|
|
63
|
+
return (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
|
|
64
|
+
const buildGradle = config.modResults;
|
|
65
|
+
// Check if ML Kit is already added
|
|
66
|
+
if (!buildGradle.contents.includes('com.google.mlkit:face-detection')) {
|
|
67
|
+
// Add ML Kit dependency in dependencies block
|
|
68
|
+
buildGradle.contents = buildGradle.contents.replace(/dependencies\s*{/, `dependencies {
|
|
69
|
+
// SmartCamera ML Kit Face Detection
|
|
70
|
+
implementation 'com.google.mlkit:face-detection:16.1.5'`);
|
|
71
|
+
}
|
|
72
|
+
return config;
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Add proguard rules for ML Kit
|
|
77
|
+
*/
|
|
78
|
+
const withProguardRules = (config, options) => {
|
|
79
|
+
if (!options.enableMLKit) {
|
|
80
|
+
return config;
|
|
81
|
+
}
|
|
82
|
+
return (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
|
|
83
|
+
const buildGradle = config.modResults;
|
|
84
|
+
// Check if proguard is already configured for ML Kit
|
|
85
|
+
if (!buildGradle.contents.includes('mlkit-proguard-rules.pro')) {
|
|
86
|
+
// Add proguard configuration in release build type
|
|
87
|
+
buildGradle.contents = buildGradle.contents.replace(/buildTypes\s*{\s*release\s*{/, `buildTypes {
|
|
88
|
+
release {
|
|
89
|
+
// SmartCamera ML Kit Proguard rules
|
|
90
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'`);
|
|
91
|
+
}
|
|
92
|
+
return config;
|
|
93
|
+
});
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Android configuration for react-native-smart-camera
|
|
97
|
+
*/
|
|
98
|
+
const withSmartCameraAndroid = (config, options) => {
|
|
99
|
+
// Add permissions
|
|
100
|
+
config = withPermissions(config, options);
|
|
101
|
+
// Add ML Kit dependency if enabled
|
|
102
|
+
config = withMLKitDependency(config, options);
|
|
103
|
+
// Add proguard rules if ML Kit enabled
|
|
104
|
+
config = withProguardRules(config, options);
|
|
105
|
+
return config;
|
|
106
|
+
};
|
|
107
|
+
exports.withSmartCameraAndroid = withSmartCameraAndroid;
|
|
108
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2l0aFNtYXJ0Q2FtZXJhQW5kcm9pZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy93aXRoU21hcnRDYW1lcmFBbmRyb2lkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHlEQU04QjtBQU85Qjs7R0FFRztBQUNILE1BQU0sZUFBZSxHQUF1QyxDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsRUFBRTtJQUMvRSxPQUFPLElBQUEsb0NBQW1CLEVBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxFQUFFLEVBQUU7UUFDNUMsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztRQUVuQyxrQ0FBa0M7UUFDbEMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1lBQzFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDNUMsQ0FBQztRQUVELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUV6RCxvQkFBb0I7UUFDcEIsTUFBTSxnQkFBZ0IsR0FBRywyQkFBMkIsQ0FBQztRQUNyRCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLGNBQWMsQ0FBQyxLQUFLLGdCQUFnQixDQUFDLEVBQUUsQ0FBQztZQUN6RSxXQUFXLENBQUMsSUFBSSxDQUFDO2dCQUNmLENBQUMsRUFBRSxFQUFFLGNBQWMsRUFBRSxnQkFBZ0IsRUFBRTthQUN4QyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsd0JBQXdCO1FBQ3hCLE1BQU0sYUFBYSxHQUFHLGlDQUFpQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMs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RkFHdUYsQ0FDeEYsQ0FBQztRQUNKLENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQztBQUVGOztHQUVHO0FBQ0ksTUFBTSxzQkFBc0IsR0FBdUMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUU7SUFDNUYsa0JBQWtCO0lBQ2xCLE1BQU0sR0FBRyxlQUFlLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRTFDLG1DQUFtQztJQUNuQyxNQUFNLEdBQUcsbUJBQW1CLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRTlDLHVDQUF1QztJQUN2QyxNQUFNLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRTVDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQztBQVhXLFFBQUEsc0JBQXNCLDBCQVdqQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbmZpZ1BsdWdpbixcbiAgd2l0aEFuZHJvaWRNYW5pZmVzdCxcbiAgd2l0aEFwcEJ1aWxkR3JhZGxlLFxuICB3aXRoUHJvamVjdEJ1aWxkR3JhZGxlLFxuICBBbmRyb2lkQ29uZmlnLFxufSBmcm9tICdAZXhwby9jb25maWctcGx1Z2lucyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQW5kcm9pZFBsdWdpbk9wdGlvbnMge1xuICBlbmFibGVNTEtpdDogYm9vbGVhbjtcbiAgZW5hYmxlV2ViUlRDOiBib29sZWFuO1xufVxuXG4vKipcbiAqIEFkZCBjYW1lcmEgYW5kIG1pY3JvcGhvbmUgcGVybWlzc2lvbnMgdG8gQW5kcm9pZE1hbmlmZXN0LnhtbFxuICovXG5jb25zdCB3aXRoUGVybWlzc2lvbnM6IENvbmZpZ1BsdWdpbjxBbmRyb2lkUGx1Z2luT3B0aW9ucz4gPSAoY29uZmlnLCBfb3B0aW9ucykgPT4ge1xuICByZXR1cm4gd2l0aEFuZHJvaWRNYW5pZmVzdChjb25maWcsIChjb25maWcpID0+IHtcbiAgICBjb25zdCBtYW5pZmVzdCA9IGNvbmZpZy5tb2RSZXN1bHRzO1xuXG4gICAgLy8gRW5zdXJlIHBlcm1pc3Npb25zIGFycmF5IGV4aXN0c1xuICAgIGlmICghbWFuaWZlc3QubWFuaWZlc3RbJ3VzZXMtcGVybWlzc2lvbiddKSB7XG4gICAgICBtYW5pZmVzdC5tYW5pZmVzdFsndXNlcy1wZXJtaXNzaW9uJ10gPSBbXTtcbiAgICB9XG5cbiAgICBjb25zdCBwZXJtaXNzaW9ucyA9IG1hbmlmZXN0Lm1hbmlmZXN0Wyd1c2VzLXBlcm1pc3Npb24nXTtcblxuICAgIC8vIENhbWVyYSBwZXJtaXNzaW9uXG4gICAgY29uc3QgY2FtZXJhUGVybWlzc2lvbiA9ICdhbmRyb2lkLnBlcm1pc3Npb24uQ0FNRVJBJztcbiAgICBpZiAoIXBlcm1pc3Npb25zLnNvbWUoKHApID0+IHAuJD8uWydhbmRyb2lkOm5hbWUnXSA9PT0gY2FtZXJhUGVybWlzc2lvbikpIHtcbiAgICAgIHBlcm1pc3Npb25zLnB1c2goe1xuICAgICAgICAkOiB7ICdhbmRyb2lkOm5hbWUnOiBjYW1lcmFQZXJtaXNzaW9uIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBNaWNyb3Bob25lIHBlcm1pc3Npb25cbiAgICBjb25zdCBtaWNQZXJtaXNzaW9uID0gJ2FuZHJvaWQucGVybWlzc2lvbi5SRUNPUkRfQVVESU8nO1xuICAgIGlmICghcGVybWlzc2lvbnMuc29tZSgocCkgPT4gcC4kPy5bJ2FuZHJvaWQ6bmFtZSddID09PSBtaWNQZXJtaXNzaW9uKSkge1xuICAgICAgcGVybWlzc2lvbnMucHVzaCh7XG4gICAgICAgICQ6IHsgJ2FuZHJvaWQ6bmFtZSc6IG1pY1Blcm1pc3Npb24gfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIENhbWVyYSBoYXJkd2FyZSBmZWF0dXJlXG4gICAgaWYgKCFtYW5pZmVzdC5tYW5pZmVzdFsndXNlcy1mZWF0dXJlJ10pIHtcbiAgICAgIG1hbmlmZXN0Lm1hbmlmZXN0Wyd1c2VzLWZlYXR1cmUnXSA9IFtdO1xuICAgIH1cblxuICAgIGNvbnN0IGZlYXR1cmVzID0gbWFuaWZlc3QubWFuaWZlc3RbJ3VzZXMtZmVhdHVyZSddO1xuICAgIGNvbnN0IGNhbWVyYUZlYXR1cmUgPSAnYW5kcm9pZC5oYXJkd2FyZS5jYW1lcmEnO1xuICAgIGlmICghZmVhdHVyZXMuc29tZSgoZikgPT4gZi4kPy5bJ2FuZHJvaWQ6bmFtZSddID09PSBjYW1lcmFGZWF0dXJlKSkge1xuICAgICAgZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICQ6IHtcbiAgICAgICAgICAnYW5kcm9pZDpuYW1lJzogY2FtZXJhRmVhdHVyZSxcbiAgICAgICAgICAnYW5kcm9pZDpyZXF1aXJlZCc6ICdmYWxzZScsXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCBjYW1lcmFBdXRvRm9jdXMgPSAnYW5kcm9pZC5oYXJkd2FyZS5jYW1lcmEuYXV0b2ZvY3VzJztcbiAgICBpZiAoIWZlYXR1cmVzLnNvbWUoKGYpID0+IGYuJD8uWydhbmRyb2lkOm5hbWUnXSA9PT0gY2FtZXJhQXV0b0ZvY3VzKSkge1xuICAgICAgZmVhdHVyZXMucHVzaCh7XG4gICAgICAgICQ6IHtcbiAgICAgICAgICAnYW5kcm9pZDpuYW1lJzogY2FtZXJhQXV0b0ZvY3VzLFxuICAgICAgICAgICdhbmRyb2lkOnJlcXVpcmVkJzogJ2ZhbHNlJyxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBjb25maWc7XG4gIH0pO1xufTtcblxuLyoqXG4gKiBBZGQgTUwgS2l0IGRlcGVuZGVuY3kgdG8gYXBwIGJ1aWxkLmdyYWRsZVxuICovXG5jb25zdCB3aXRoTUxLaXREZXBlbmRlbmN5OiBDb25maWdQbHVnaW48QW5kcm9pZFBsdWdpbk9wdGlvbnM+ID0gKGNvbmZpZywgb3B0aW9ucykgPT4ge1xuICBpZiAoIW9wdGlvbnMuZW5hYmxlTUxLaXQpIHtcbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG5cbiAgcmV0dXJuIHdpdGhBcHBCdWlsZEdyYWRsZShjb25maWcsIChjb25maWcpID0+IHtcbiAgICBjb25zdCBidWlsZEdyYWRsZSA9IGNvbmZpZy5tb2RSZXN1bHRzO1xuXG4gICAgLy8gQ2hlY2sgaWYgTUwgS2l0IGlzIGFscmVhZHkgYWRkZWRcbiAgICBpZiAoIWJ1aWxkR3JhZGxlLmNvbnRlbnRzLmluY2x1ZGVzKCdjb20uZ29vZ2xlLm1sa2l0OmZhY2UtZGV0ZWN0aW9uJykpIHtcbiAgICAgIC8vIEFkZCBNTCBLaXQgZGVwZW5kZW5jeSBpbiBkZXBlbmRlbmNpZXMgYmxvY2tcbiAgICAgIGJ1aWxkR3JhZGxlLmNvbnRlbnRzID0gYnVpbGRHcmFkbGUuY29udGVudHMucmVwbGFjZShcbiAgICAgICAgL2RlcGVuZGVuY2llc1xccyp7LyxcbiAgICAgICAgYGRlcGVuZGVuY2llcyB7XG4gICAgLy8gU21hcnRDYW1lcmEgTUwgS2l0IEZhY2UgRGV0ZWN0aW9uXG4gICAgaW1wbGVtZW50YXRpb24gJ2NvbS5nb29nbGUubWxraXQ6ZmFjZS1kZXRlY3Rpb246MTYuMS41J2BcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZztcbiAgfSk7XG59O1xuXG4vKipcbiAqIEFkZCBwcm9ndWFyZCBydWxlcyBmb3IgTUwgS2l0XG4gKi9cbmNvbnN0IHdpdGhQcm9ndWFyZFJ1bGVzOiBDb25maWdQbHVnaW48QW5kcm9pZFBsdWdpbk9wdGlvbnM+ID0gKGNvbmZpZywgb3B0aW9ucykgPT4ge1xuICBpZiAoIW9wdGlvbnMuZW5hYmxlTUxLaXQpIHtcbiAgICByZXR1cm4gY29uZmlnO1xuICB9XG5cbiAgcmV0dXJuIHdpdGhBcHBCdWlsZEdyYWRsZShjb25maWcsIChjb25maWcpID0+IHtcbiAgICBjb25zdCBidWlsZEdyYWRsZSA9IGNvbmZpZy5tb2RSZXN1bHRzO1xuXG4gICAgLy8gQ2hlY2sgaWYgcHJvZ3VhcmQgaXMgYWxyZWFkeSBjb25maWd1cmVkIGZvciBNTCBLaXRcbiAgICBpZiAoIWJ1aWxkR3JhZGxlLmNvbnRlbnRzLmluY2x1ZGVzKCdtbGtpdC1wcm9ndWFyZC1ydWxlcy5wcm8nKSkge1xuICAgICAgLy8gQWRkIHByb2d1YXJkIGNvbmZpZ3VyYXRpb24gaW4gcmVsZWFzZSBidWlsZCB0eXBlXG4gICAgICBidWlsZEdyYWRsZS5jb250ZW50cyA9IGJ1aWxkR3JhZGxlLmNvbnRlbnRzLnJlcGxhY2UoXG4gICAgICAgIC9idWlsZFR5cGVzXFxzKntcXHMqcmVsZWFzZVxccyp7LyxcbiAgICAgICAgYGJ1aWxkVHlwZXMge1xuICAgICAgICByZWxlYXNlIHtcbiAgICAgICAgICAgIC8vIFNtYXJ0Q2FtZXJhIE1MIEtpdCBQcm9ndWFyZCBydWxlc1xuICAgICAgICAgICAgcHJvZ3VhcmRGaWxlcyBnZXREZWZhdWx0UHJvZ3VhcmRGaWxlKCdwcm9ndWFyZC1hbmRyb2lkLnR4dCcpLCAncHJvZ3VhcmQtcnVsZXMucHJvJ2BcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZztcbiAgfSk7XG59O1xuXG4vKipcbiAqIEFuZHJvaWQgY29uZmlndXJhdGlvbiBmb3IgcmVhY3QtbmF0aXZlLXNtYXJ0LWNhbWVyYVxuICovXG5leHBvcnQgY29uc3Qgd2l0aFNtYXJ0Q2FtZXJhQW5kcm9pZDogQ29uZmlnUGx1Z2luPEFuZHJvaWRQbHVnaW5PcHRpb25zPiA9IChjb25maWcsIG9wdGlvbnMpID0+IHtcbiAgLy8gQWRkIHBlcm1pc3Npb25zXG4gIGNvbmZpZyA9IHdpdGhQZXJtaXNzaW9ucyhjb25maWcsIG9wdGlvbnMpO1xuXG4gIC8vIEFkZCBNTCBLaXQgZGVwZW5kZW5jeSBpZiBlbmFibGVkXG4gIGNvbmZpZyA9IHdpdGhNTEtpdERlcGVuZGVuY3koY29uZmlnLCBvcHRpb25zKTtcblxuICAvLyBBZGQgcHJvZ3VhcmQgcnVsZXMgaWYgTUwgS2l0IGVuYWJsZWRcbiAgY29uZmlnID0gd2l0aFByb2d1YXJkUnVsZXMoY29uZmlnLCBvcHRpb25zKTtcblxuICByZXR1cm4gY29uZmlnO1xufTtcblxuIl19
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
export interface IOSPluginOptions {
|
|
3
|
+
cameraPermissionText: string;
|
|
4
|
+
microphonePermissionText: string;
|
|
5
|
+
enableMLKit: boolean;
|
|
6
|
+
enableWebRTC: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* iOS configuration for react-native-smart-camera
|
|
10
|
+
*/
|
|
11
|
+
export declare const withSmartCameraIOS: ConfigPlugin<IOSPluginOptions>;
|