replate-camera 0.1.1
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/LICENSE +20 -0
- package/README.md +31 -0
- package/android/build.gradle +94 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/AndroidManifestNew.xml +2 -0
- package/android/src/main/java/com/replatecamera/ReplateCameraPackage.kt +17 -0
- package/android/src/main/java/com/replatecamera/ReplateCameraViewManager.kt +20 -0
- package/ios/ReplateCamera-Bridging-Header.h +3 -0
- package/ios/ReplateCameraController.swift +15 -0
- package/ios/ReplateCameraViewManager.m +24 -0
- package/ios/ReplateCameraViewManager.swift +377 -0
- package/lib/commonjs/index.js +25 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/index.js +18 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/src/index.d.ts +9 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +160 -0
- package/replate-camera.podspec +42 -0
- package/src/index.tsx +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Filippo Cavallari
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# replate-camera
|
|
2
|
+
|
|
3
|
+
Camera component for Replate Manager
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install replate-camera
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import { ReplateCameraView } from "replate-camera";
|
|
15
|
+
|
|
16
|
+
// ...
|
|
17
|
+
|
|
18
|
+
<ReplateCameraView color="tomato" />
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Contributing
|
|
22
|
+
|
|
23
|
+
See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
|
|
24
|
+
|
|
25
|
+
## License
|
|
26
|
+
|
|
27
|
+
MIT
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
3
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["ReplateCamera_kotlinVersion"]
|
|
4
|
+
|
|
5
|
+
repositories {
|
|
6
|
+
google()
|
|
7
|
+
mavenCentral()
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath "com.android.tools.build:gradle:7.2.1"
|
|
12
|
+
// noinspection DifferentKotlinGradleVersion
|
|
13
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: "kotlin-android"
|
|
23
|
+
|
|
24
|
+
if (isNewArchitectureEnabled()) {
|
|
25
|
+
apply plugin: "com.facebook.react"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
def getExtOrDefault(name) {
|
|
29
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ReplateCamera_" + name]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def getExtOrIntegerDefault(name) {
|
|
33
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReplateCamera_" + name]).toInteger()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def supportsNamespace() {
|
|
37
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
38
|
+
def major = parsed[0].toInteger()
|
|
39
|
+
def minor = parsed[1].toInteger()
|
|
40
|
+
|
|
41
|
+
// Namespace support was added in 7.3.0
|
|
42
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
android {
|
|
46
|
+
if (supportsNamespace()) {
|
|
47
|
+
namespace "com.replatecamera"
|
|
48
|
+
|
|
49
|
+
sourceSets {
|
|
50
|
+
main {
|
|
51
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
57
|
+
|
|
58
|
+
defaultConfig {
|
|
59
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
60
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
buildTypes {
|
|
65
|
+
release {
|
|
66
|
+
minifyEnabled false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
lintOptions {
|
|
71
|
+
disable "GradleCompatible"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
compileOptions {
|
|
75
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
76
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
repositories {
|
|
81
|
+
mavenCentral()
|
|
82
|
+
google()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
86
|
+
|
|
87
|
+
dependencies {
|
|
88
|
+
// For < 0.71, this will be from the local maven repo
|
|
89
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
90
|
+
//noinspection GradleDynamicVersion
|
|
91
|
+
implementation "com.facebook.react:react-native:+"
|
|
92
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
93
|
+
}
|
|
94
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.replatecamera
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.ViewManager
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ReplateCameraPackage : ReactPackage {
|
|
10
|
+
override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
|
|
11
|
+
return emptyList()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
15
|
+
return listOf(ReplateCameraViewManager())
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.replatecamera
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import android.view.View
|
|
5
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
6
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
8
|
+
|
|
9
|
+
class ReplateCameraViewManager : SimpleViewManager<View>() {
|
|
10
|
+
override fun getName() = "ReplateCameraView"
|
|
11
|
+
|
|
12
|
+
override fun createViewInstance(reactContext: ThemedReactContext): View {
|
|
13
|
+
return View(reactContext)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@ReactProp(name = "color")
|
|
17
|
+
fun setColor(view: View, color: String) {
|
|
18
|
+
view.setBackgroundColor(Color.parseColor(color))
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@objc(ReplateCameraController)
|
|
2
|
+
class ReplateCameraController: NSObject {
|
|
3
|
+
|
|
4
|
+
@objc(takePhoto:rejecter:)
|
|
5
|
+
func takePhoto(_ resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) -> Void {
|
|
6
|
+
print("Take photo")
|
|
7
|
+
resolver("Photo taken")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@objc
|
|
11
|
+
func constantsToExport() -> [String: Any]! {
|
|
12
|
+
return ["someKey": "someValue"]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#import <React/RCTViewManager.h>
|
|
2
|
+
#import <React/RCTUIManager.h>
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
|
|
5
|
+
@interface RCT_EXTERN_MODULE(ReplateCameraViewManager, RCTViewManager)
|
|
6
|
+
|
|
7
|
+
// RCT_EXPORT_VIEW_PROPERTY(rect, NSDictionary)
|
|
8
|
+
RCT_EXPORT_VIEW_PROPERTY(color, NSString)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@end
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@interface RCT_EXTERN_MODULE(ReplateCameraController, NSObject)
|
|
15
|
+
|
|
16
|
+
RCT_EXTERN_METHOD(takePhoto:(RCTPromiseResolveBlock*)resolve
|
|
17
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
18
|
+
|
|
19
|
+
+ (BOOL)requiresMainQueueSetup
|
|
20
|
+
{
|
|
21
|
+
return NO;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@end
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
import ARKit
|
|
2
|
+
import RealityKit
|
|
3
|
+
import UIKit
|
|
4
|
+
import AVFoundation
|
|
5
|
+
|
|
6
|
+
@objc(ReplateCameraViewManager)
|
|
7
|
+
class ReplateCameraViewManager: RCTViewManager {
|
|
8
|
+
|
|
9
|
+
override func view() -> (ReplateCameraView) {
|
|
10
|
+
let replCameraView = ReplateCameraView()
|
|
11
|
+
return replCameraView
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@objc override static func requiresMainQueueSetup() -> Bool {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class ReplateCameraView : UIView, ARSessionDelegate {
|
|
22
|
+
|
|
23
|
+
static var arView: ARView!
|
|
24
|
+
static var anchor: ARAnchor!
|
|
25
|
+
static var anchorEntity: AnchorEntity!
|
|
26
|
+
static var model: Entity!
|
|
27
|
+
static var spheresModels: [ModelEntity] = []
|
|
28
|
+
static var upperSpheresSet: [Bool] = [Bool](repeating: false, count: 72)
|
|
29
|
+
static var lowerSpheresSet: [Bool] = [Bool](repeating: false, count: 72)
|
|
30
|
+
|
|
31
|
+
override init(frame: CGRect) {
|
|
32
|
+
super.init(frame: frame)
|
|
33
|
+
requestCameraPermissions()
|
|
34
|
+
// setupAR()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
required init?(coder: NSCoder) {
|
|
38
|
+
super.init(coder: coder)
|
|
39
|
+
requestCameraPermissions()
|
|
40
|
+
// setupAR()
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func requestCameraPermissions(){
|
|
44
|
+
|
|
45
|
+
if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
|
|
46
|
+
print("Camera permissions already granted")
|
|
47
|
+
} else {
|
|
48
|
+
AVCaptureDevice.requestAccess(for: .video, completionHandler: { (granted: Bool) in
|
|
49
|
+
if granted {
|
|
50
|
+
print("Camera permissions granted")
|
|
51
|
+
} else {
|
|
52
|
+
print("Camera permissions denied")
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override func layoutSubviews() {
|
|
59
|
+
super.layoutSubviews()
|
|
60
|
+
|
|
61
|
+
// Now you can safely access the size
|
|
62
|
+
let width = self.frame.width
|
|
63
|
+
let height = self.frame.height
|
|
64
|
+
|
|
65
|
+
// Do something with width and height
|
|
66
|
+
print("Width: \(width), Height: \(height)")
|
|
67
|
+
self.setupAR()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func setupAR() {
|
|
71
|
+
print("Setup AR")
|
|
72
|
+
let width = self.frame.width
|
|
73
|
+
let height = self.frame.height
|
|
74
|
+
ReplateCameraView.arView = ARView(frame: CGRect(x: 0, y: 0, width: width, height: height))
|
|
75
|
+
ReplateCameraView.arView.backgroundColor = hexStringToUIColor(hexColor: "#32a852")
|
|
76
|
+
addSubview(ReplateCameraView.arView)
|
|
77
|
+
ReplateCameraView.arView.session.delegate = self
|
|
78
|
+
let configuration = ARWorldTrackingConfiguration()
|
|
79
|
+
// guard let obj = ARReferenceObject.referenceObjects(inGroupNamed: "AR Resource Group",
|
|
80
|
+
// bundle: nil)
|
|
81
|
+
// else { fatalError("See no reference object") }
|
|
82
|
+
// print(obj)
|
|
83
|
+
configuration.planeDetection = ARWorldTrackingConfiguration.PlaneDetection.horizontal
|
|
84
|
+
if #available(iOS 16.0, *) {
|
|
85
|
+
print("recommendedVideoFormatForHighResolutionFrameCapturing")
|
|
86
|
+
configuration.videoFormat = ARWorldTrackingConfiguration.recommendedVideoFormatForHighResolutionFrameCapturing ?? ARWorldTrackingConfiguration.recommendedVideoFormatFor4KResolution ?? ARWorldTrackingConfiguration.supportedVideoFormats[0]
|
|
87
|
+
} else {
|
|
88
|
+
print("Alternative high resolution method")
|
|
89
|
+
let maxResolutionFormat = ARWorldTrackingConfiguration.supportedVideoFormats.max(by: { format1, format2 in
|
|
90
|
+
let resolution1 = format1.imageResolution.width * format1.imageResolution.height
|
|
91
|
+
let resolution2 = format2.imageResolution.width * format2.imageResolution.height
|
|
92
|
+
return resolution1 < resolution2
|
|
93
|
+
})!
|
|
94
|
+
configuration.videoFormat = maxResolutionFormat
|
|
95
|
+
}
|
|
96
|
+
// configuration.detectionObjects = obj
|
|
97
|
+
ReplateCameraView.arView.session.run(configuration)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
|
|
101
|
+
print("ANCHOR FOUND")
|
|
102
|
+
if (ReplateCameraView.anchor == nil){
|
|
103
|
+
guard let _anchor = anchors.first else { return }
|
|
104
|
+
ReplateCameraView.anchor = _anchor
|
|
105
|
+
}
|
|
106
|
+
if (ReplateCameraView.model == nil && ReplateCameraView.anchorEntity == nil){
|
|
107
|
+
let anchorTransform = ReplateCameraView.anchor.transform
|
|
108
|
+
// let path = Bundle.main.path(forResource: "anchor", ofType: "usdz")!
|
|
109
|
+
// let url = URL(fileURLWithPath: path)
|
|
110
|
+
// let entity: ModelEntity = try! ModelEntity.loadModel(contentsOf: url)
|
|
111
|
+
|
|
112
|
+
// if #available(iOS 15.0, *) {
|
|
113
|
+
// entity.model!.mesh.
|
|
114
|
+
// ReplateCameraView.spheresModels = Array(entity.model!.mesh.contents.models)
|
|
115
|
+
// }
|
|
116
|
+
// entity.scale *= 4.5
|
|
117
|
+
// entity.position = SIMD3(anchorTransform.columns.3.x, anchorTransform.columns.3.y, anchorTransform.columns.3.z)
|
|
118
|
+
|
|
119
|
+
func createSphere(position: SIMD3<Float>) -> ModelEntity {
|
|
120
|
+
let sphereMesh = MeshResource.generateSphere(radius: 0.0025)
|
|
121
|
+
let sphereEntity = ModelEntity(mesh: sphereMesh, materials: [SimpleMaterial(color: .white.withAlphaComponent(0.7), isMetallic: false)])
|
|
122
|
+
sphereEntity.position = position
|
|
123
|
+
return sphereEntity
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
func createSpheres(y: Float){
|
|
127
|
+
let radius = Float(0.1)
|
|
128
|
+
for i in 0..<72 {
|
|
129
|
+
let angle = Float(i) * (Float.pi / 180) * 5 // 10 degrees in radians
|
|
130
|
+
let x = radius * cos(angle)
|
|
131
|
+
let z = radius * sin(angle)
|
|
132
|
+
var spherePosition = SIMD3<Float>(x, y, z)
|
|
133
|
+
var sphereEntity = createSphere(position: spherePosition)
|
|
134
|
+
ReplateCameraView.spheresModels.append(sphereEntity)
|
|
135
|
+
ReplateCameraView.anchorEntity.addChild(sphereEntity)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
ReplateCameraView.anchorEntity = AnchorEntity()
|
|
140
|
+
createSpheres(y: 0.0)
|
|
141
|
+
createSpheres(y: 0.3)
|
|
142
|
+
ReplateCameraView.arView.scene.anchors.append(ReplateCameraView.anchorEntity)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// @objc func setCameraRect(_ node: NSNumber, rect: NSDictionary) {
|
|
147
|
+
// let x = rect["x"] as? CGFloat ?? 0
|
|
148
|
+
// let y = rect["y"] as? CGFloat ?? 0
|
|
149
|
+
// let width = rect["width"] as? CGFloat ?? 0
|
|
150
|
+
// let height = rect["height"] as? CGFloat ?? 0
|
|
151
|
+
//// arView.(CGRect(x: x, y: y, width: width, height: height))
|
|
152
|
+
// }
|
|
153
|
+
|
|
154
|
+
@objc var color: String = "" {
|
|
155
|
+
didSet {
|
|
156
|
+
self.backgroundColor = hexStringToUIColor(hexColor: color)
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
func hexStringToUIColor(hexColor: String) -> UIColor {
|
|
161
|
+
let stringScanner = Scanner(string: hexColor)
|
|
162
|
+
|
|
163
|
+
if(hexColor.hasPrefix("#")) {
|
|
164
|
+
stringScanner.scanLocation = 1
|
|
165
|
+
}
|
|
166
|
+
var color: UInt32 = 0
|
|
167
|
+
stringScanner.scanHexInt32(&color)
|
|
168
|
+
|
|
169
|
+
let r = CGFloat(Int(color >> 16) & 0x000000FF)
|
|
170
|
+
let g = CGFloat(Int(color >> 8) & 0x000000FF)
|
|
171
|
+
let b = CGFloat(Int(color) & 0x000000FF)
|
|
172
|
+
|
|
173
|
+
return UIColor(red: r / 255.0, green: g / 255.0, blue: b / 255.0, alpha: 1)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
func session(_ session: ARSession, didUpdate frame: ARFrame) {
|
|
177
|
+
// Handle AR frame updates
|
|
178
|
+
// You can perform actions here, such as updating the AR content based on the camera frame
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
func sessionWasInterrupted(_ session: ARSession) {
|
|
182
|
+
// Handle session interruption (e.g., app goes to the background)
|
|
183
|
+
|
|
184
|
+
// Pause the AR session to save resources
|
|
185
|
+
ReplateCameraView.arView.session.pause()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
func sessionInterruptionEnded(_ session: ARSession) {
|
|
189
|
+
// Handle resuming session after interruption
|
|
190
|
+
|
|
191
|
+
// Resume the AR session
|
|
192
|
+
ReplateCameraView.arView.session.run(ARWorldTrackingConfiguration())
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@objc(ReplateCameraController)
|
|
199
|
+
class ReplateCameraController: NSObject {
|
|
200
|
+
|
|
201
|
+
@objc(takePhoto:rejecter:)
|
|
202
|
+
func takePhoto(_ resolver: RCTPromiseResolveBlock, rejecter: RCTPromiseRejectBlock) -> Void {
|
|
203
|
+
|
|
204
|
+
//DEVICE ORIENTATION
|
|
205
|
+
guard let anchorNode = ReplateCameraView.anchorEntity else {
|
|
206
|
+
rejecter("[ReplateCameraController]", "Error saving photo", NSError(domain: "ReplateCameraController", code: 001, userInfo: nil));
|
|
207
|
+
return
|
|
208
|
+
}
|
|
209
|
+
// Assuming you have two points
|
|
210
|
+
let point1 = SIMD3<Float>(anchorNode.position.x,
|
|
211
|
+
anchorNode.position.y,
|
|
212
|
+
anchorNode.position.z)
|
|
213
|
+
let point2 = SIMD3<Float>(anchorNode.position.x,
|
|
214
|
+
anchorNode.position.y + 0.3,
|
|
215
|
+
anchorNode.position.z)
|
|
216
|
+
|
|
217
|
+
// Function to calculate the angle between two vectors
|
|
218
|
+
func angleBetweenVectors(_ vector1: SIMD3<Float>, _ vector2: SIMD3<Float>) -> Float {
|
|
219
|
+
let dotProduct = dot(normalize(vector1), normalize(vector2))
|
|
220
|
+
return acos(dotProduct)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Threshold angle for considering if the device is pointing towards a point
|
|
224
|
+
let thresholdAngle: Float = 0.3 // Adjust this threshold as needed
|
|
225
|
+
var deviceTargetInFocus = -1
|
|
226
|
+
// Check if the device is pointing towards one of the two points
|
|
227
|
+
if let cameraTransform = ReplateCameraView.arView.session.currentFrame?.camera.transform {
|
|
228
|
+
let deviceDirection = SIMD3<Float>(-cameraTransform.columns.2.x, -cameraTransform.columns.2.y, -cameraTransform.columns.2.z)
|
|
229
|
+
|
|
230
|
+
let cameraPosition = SIMD3<Float>(cameraTransform.columns.3.x, cameraTransform.columns.3.y, cameraTransform.columns.3.z)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
let directionToFirstPoint = normalize(point1 - cameraPosition)
|
|
234
|
+
let directionToSecondPoint = normalize(point2 - cameraPosition)
|
|
235
|
+
|
|
236
|
+
let angleToFirstPoint = angleBetweenVectors(deviceDirection, directionToFirstPoint)
|
|
237
|
+
let angleToSecondPoint = angleBetweenVectors(deviceDirection, directionToSecondPoint)
|
|
238
|
+
print("Camera Y: \(cameraPosition.y)")
|
|
239
|
+
let isPointingAtFirstPoint = angleToFirstPoint < thresholdAngle && cameraPosition.y < 0.25
|
|
240
|
+
let isPointingAtSecondPoint = angleToSecondPoint < thresholdAngle && cameraPosition.y >= 0.25
|
|
241
|
+
if (isPointingAtFirstPoint) {
|
|
242
|
+
deviceTargetInFocus = 0
|
|
243
|
+
}else if(isPointingAtSecondPoint){
|
|
244
|
+
deviceTargetInFocus = 1
|
|
245
|
+
}
|
|
246
|
+
// Now you can determine if the device is pointing towards one of the two points
|
|
247
|
+
print("Is pointing at first point: \(isPointingAtFirstPoint)")
|
|
248
|
+
print("Is pointing at second point: \(isPointingAtSecondPoint)")
|
|
249
|
+
} else {
|
|
250
|
+
print("Camera transform data not available")
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
print("Take photo")
|
|
254
|
+
if(deviceTargetInFocus != -1){
|
|
255
|
+
if let image = ReplateCameraView.arView?.session.currentFrame?.capturedImage {
|
|
256
|
+
let ciimg = CIImage(cvImageBuffer: image)
|
|
257
|
+
let ciImage = ciimg
|
|
258
|
+
let cgImage = ReplateCameraController.cgImage(from: ciImage)!
|
|
259
|
+
let finImage = UIImage(cgImage: cgImage)
|
|
260
|
+
print("Saving photo")
|
|
261
|
+
if let url = ReplateCameraController.saveImageAsJPEG(finImage) {
|
|
262
|
+
resolver(url.absoluteString)
|
|
263
|
+
print("Saved photo")
|
|
264
|
+
updateSpheres(deviceTargetInFocus: deviceTargetInFocus)
|
|
265
|
+
return
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
print("Error saving photo")
|
|
271
|
+
rejecter("[ReplateCameraController]", "Error saving photo", NSError(domain: "ReplateCameraController", code: 001, userInfo: nil))
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
static func cgImage(from ciImage: CIImage) -> CGImage? {
|
|
277
|
+
let context = CIContext(options: nil)
|
|
278
|
+
return context.createCGImage(ciImage, from: ciImage.extent)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
static func saveImageAsJPEG(_ image: UIImage) -> URL? {
|
|
282
|
+
// Convert UIImage to Data with JPEG representation
|
|
283
|
+
guard let imageData = image.jpegData(compressionQuality: 1.0) else {
|
|
284
|
+
// Handle error if unable to convert to JPEG data
|
|
285
|
+
print("Error converting UIImage to JPEG data")
|
|
286
|
+
return nil
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Get the temporary directory URL
|
|
290
|
+
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
|
291
|
+
|
|
292
|
+
// Create a unique filename (you can use a UUID or any other method to generate a unique name)
|
|
293
|
+
let uniqueFilename = "image_\(Date().timeIntervalSince1970).jpg"
|
|
294
|
+
|
|
295
|
+
// Combine the temporary directory URL with the unique filename to get the full file URL
|
|
296
|
+
let fileURL = temporaryDirectoryURL.appendingPathComponent(uniqueFilename)
|
|
297
|
+
|
|
298
|
+
do {
|
|
299
|
+
// Write the JPEG data to the file
|
|
300
|
+
try imageData.write(to: fileURL, options: .atomic)
|
|
301
|
+
|
|
302
|
+
// Print the file URL for reference
|
|
303
|
+
print("Image saved at: \(fileURL.absoluteString)")
|
|
304
|
+
return fileURL
|
|
305
|
+
} catch {
|
|
306
|
+
// Handle the error if unable to write to the file
|
|
307
|
+
print("Error saving image: \(error.localizedDescription)")
|
|
308
|
+
return nil
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@objc
|
|
314
|
+
func constantsToExport() -> [String: Any]! {
|
|
315
|
+
return ["someKey": "someValue"]
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
func updateSpheres(deviceTargetInFocus: Int) {
|
|
319
|
+
guard let anchorNode = ReplateCameraView.anchorEntity else { return }
|
|
320
|
+
|
|
321
|
+
// Get the camera's pose
|
|
322
|
+
if let frame = ReplateCameraView.arView.session.currentFrame {
|
|
323
|
+
let cameraTransform = frame.camera.transform
|
|
324
|
+
|
|
325
|
+
// Calculate the angle between the camera and the anchor
|
|
326
|
+
let anchorPosition = SCNVector3(anchorNode.position.x,
|
|
327
|
+
anchorNode.position.y,
|
|
328
|
+
anchorNode.position.z)
|
|
329
|
+
let cameraPosition = SCNVector3(cameraTransform.columns.3.x,
|
|
330
|
+
cameraTransform.columns.3.y,
|
|
331
|
+
cameraTransform.columns.3.z)
|
|
332
|
+
|
|
333
|
+
let angleToAnchor = calculateAngle(cameraPosition, anchorPosition)
|
|
334
|
+
|
|
335
|
+
let sphereIndex = Int(floor(angleToAnchor/5))
|
|
336
|
+
var mesh: ModelEntity?
|
|
337
|
+
if(deviceTargetInFocus == 1 && !ReplateCameraView.upperSpheresSet[sphereIndex]){
|
|
338
|
+
ReplateCameraView.upperSpheresSet[sphereIndex] = true
|
|
339
|
+
mesh = ReplateCameraView.spheresModels[72+sphereIndex]
|
|
340
|
+
}else if(deviceTargetInFocus == 0 && !ReplateCameraView.lowerSpheresSet[sphereIndex]){
|
|
341
|
+
ReplateCameraView.lowerSpheresSet[sphereIndex] = true
|
|
342
|
+
mesh = ReplateCameraView.spheresModels[sphereIndex]
|
|
343
|
+
}
|
|
344
|
+
if (mesh != nil){
|
|
345
|
+
let material = SimpleMaterial(color: .green, isMetallic: false)
|
|
346
|
+
mesh?.model?.materials[0] = material
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
func calculateAngle(_ vector1: SCNVector3, _ vector2: SCNVector3) -> Float {
|
|
352
|
+
// Calculate the angle in 2D plane (x-z plane) using atan2
|
|
353
|
+
let angle = atan2(vector1.z, vector1.x)
|
|
354
|
+
|
|
355
|
+
// Convert from radians to degrees
|
|
356
|
+
var angleInDegrees = GLKMathRadiansToDegrees(Float(angle))
|
|
357
|
+
|
|
358
|
+
// Adjust the angle to be between 0 and 360 degrees
|
|
359
|
+
if angleInDegrees < 0 {
|
|
360
|
+
angleInDegrees += 360
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return angleInDegrees
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
extension SCNVector3 {
|
|
369
|
+
func normalized() -> SCNVector3 {
|
|
370
|
+
let length = sqrt(x*x + y*y + z*z)
|
|
371
|
+
return SCNVector3(x/length, y/length, z/length)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
static func Dot(_ a: SCNVector3, _ b: SCNVector3) -> Float {
|
|
375
|
+
return a.x*b.x + a.y*b.y + a.z*b.z
|
|
376
|
+
}
|
|
377
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ReplateCameraView = void 0;
|
|
7
|
+
exports.takePhoto = takePhoto;
|
|
8
|
+
var _reactNative = require("react-native");
|
|
9
|
+
const LINKING_ERROR = `The package 'replate-camera' doesn't seem to be linked. Make sure: \n\n` + _reactNative.Platform.select({
|
|
10
|
+
ios: "- You have run 'pod install'\n",
|
|
11
|
+
default: ''
|
|
12
|
+
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
13
|
+
const ComponentName = 'ReplateCameraView';
|
|
14
|
+
const ReplateCameraView = exports.ReplateCameraView = _reactNative.UIManager.getViewManagerConfig(ComponentName) != null ? (0, _reactNative.requireNativeComponent)(ComponentName) : () => {
|
|
15
|
+
throw new Error(LINKING_ERROR);
|
|
16
|
+
};
|
|
17
|
+
const ReplateCameraModule = _reactNative.NativeModules.ReplateCameraController ? _reactNative.NativeModules.ReplateCameraController : new Proxy({}, {
|
|
18
|
+
get() {
|
|
19
|
+
throw new Error(LINKING_ERROR);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
function takePhoto() {
|
|
23
|
+
return ReplateCameraModule.takePhoto();
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNative","require","LINKING_ERROR","Platform","select","ios","default","ComponentName","ReplateCameraView","exports","UIManager","getViewManagerConfig","requireNativeComponent","Error","ReplateCameraModule","NativeModules","ReplateCameraController","Proxy","get","takePhoto"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAQA,MAAMC,aAAa,GAChB,yEAAwE,GACzEC,qBAAQ,CAACC,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAQjC,MAAMC,aAAa,GAAG,mBAAmB;AAElC,MAAMC,iBAAiB,GAAAC,OAAA,CAAAD,iBAAA,GAC5BE,sBAAS,CAACC,oBAAoB,CAACJ,aAAa,CAAC,IAAI,IAAI,GACjD,IAAAK,mCAAsB,EAAqBL,aAAa,CAAC,GACzD,MAAM;EACJ,MAAM,IAAIM,KAAK,CAACX,aAAa,CAAC;AAChC,CAAC;AAEP,MAAMY,mBAAmB,GAAGC,0BAAa,CAACC,uBAAuB,GAC7DD,0BAAa,CAACC,uBAAuB,GACrC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIL,KAAK,CAACX,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEE,SAASiB,SAASA,CAAA,EAAoB;EAC3C,OAAOL,mBAAmB,CAACK,SAAS,CAAC,CAAC;AACxC","ignoreList":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { requireNativeComponent, UIManager, Platform, NativeModules } from 'react-native';
|
|
2
|
+
const LINKING_ERROR = `The package 'replate-camera' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
|
|
3
|
+
ios: "- You have run 'pod install'\n",
|
|
4
|
+
default: ''
|
|
5
|
+
}) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
|
|
6
|
+
const ComponentName = 'ReplateCameraView';
|
|
7
|
+
export const ReplateCameraView = UIManager.getViewManagerConfig(ComponentName) != null ? requireNativeComponent(ComponentName) : () => {
|
|
8
|
+
throw new Error(LINKING_ERROR);
|
|
9
|
+
};
|
|
10
|
+
const ReplateCameraModule = NativeModules.ReplateCameraController ? NativeModules.ReplateCameraController : new Proxy({}, {
|
|
11
|
+
get() {
|
|
12
|
+
throw new Error(LINKING_ERROR);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
export function takePhoto() {
|
|
16
|
+
return ReplateCameraModule.takePhoto();
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["requireNativeComponent","UIManager","Platform","NativeModules","LINKING_ERROR","select","ios","default","ComponentName","ReplateCameraView","getViewManagerConfig","Error","ReplateCameraModule","ReplateCameraController","Proxy","get","takePhoto"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,SACEA,sBAAsB,EACtBC,SAAS,EACTC,QAAQ,EAERC,aAAa,QACR,cAAc;AAErB,MAAMC,aAAa,GAChB,yEAAwE,GACzEF,QAAQ,CAACG,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;AAQjC,MAAMC,aAAa,GAAG,mBAAmB;AAEzC,OAAO,MAAMC,iBAAiB,GAC5BR,SAAS,CAACS,oBAAoB,CAACF,aAAa,CAAC,IAAI,IAAI,GACjDR,sBAAsB,CAAqBQ,aAAa,CAAC,GACzD,MAAM;EACJ,MAAM,IAAIG,KAAK,CAACP,aAAa,CAAC;AAChC,CAAC;AAEP,MAAMQ,mBAAmB,GAAGT,aAAa,CAACU,uBAAuB,GAC7DV,aAAa,CAACU,uBAAuB,GACrC,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIJ,KAAK,CAACP,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,OAAO,SAASY,SAASA,CAAA,EAAoB;EAC3C,OAAOJ,mBAAmB,CAACI,SAAS,CAAC,CAAC;AACxC","ignoreList":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ViewStyle } from 'react-native';
|
|
2
|
+
type ReplateCameraProps = {
|
|
3
|
+
color: string;
|
|
4
|
+
style: ViewStyle;
|
|
5
|
+
};
|
|
6
|
+
export declare const ReplateCameraView: import("react-native").HostComponent<ReplateCameraProps> | (() => never);
|
|
7
|
+
export declare function takePhoto(): Promise<string>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,cAAc,CAAC;AAQtB,KAAK,kBAAkB,GAAG;IAExB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;CAClB,CAAC;AAIF,eAAO,MAAM,iBAAiB,0EAKvB,CAAC;AAaR,wBAAgB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAE3C"}
|
package/package.json
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "replate-camera",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Camera component for Replate Manager",
|
|
5
|
+
"main": "lib/commonjs/index",
|
|
6
|
+
"module": "lib/module/index",
|
|
7
|
+
"types": "lib/typescript/src/index.d.ts",
|
|
8
|
+
"react-native": "src/index",
|
|
9
|
+
"source": "src/index",
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"lib",
|
|
13
|
+
"android",
|
|
14
|
+
"ios",
|
|
15
|
+
"cpp",
|
|
16
|
+
"*.podspec",
|
|
17
|
+
"!ios/build",
|
|
18
|
+
"!android/build",
|
|
19
|
+
"!android/gradle",
|
|
20
|
+
"!android/gradlew",
|
|
21
|
+
"!android/gradlew.bat",
|
|
22
|
+
"!android/local.properties",
|
|
23
|
+
"!**/__tests__",
|
|
24
|
+
"!**/__fixtures__",
|
|
25
|
+
"!**/__mocks__",
|
|
26
|
+
"!**/.*"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"example": "yarn workspace replate-camera-example",
|
|
30
|
+
"test": "jest",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
33
|
+
"clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
|
|
34
|
+
"prepare": "bob build",
|
|
35
|
+
"release": "release-it"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"react-native",
|
|
39
|
+
"ios",
|
|
40
|
+
"android"
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/ReplateItaly/replate-camera.git"
|
|
45
|
+
},
|
|
46
|
+
"author": "Filippo Cavallari <filippo.cavallari99@gmail.com> (https://github.com/Filocava99)",
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/ReplateItaly/replate-camera/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/ReplateItaly/replate-camera#readme",
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"registry": "https://registry.npmjs.org/"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@commitlint/config-conventional": "^17.0.2",
|
|
57
|
+
"@evilmartians/lefthook": "^1.5.0",
|
|
58
|
+
"@react-native/eslint-config": "^0.73.1",
|
|
59
|
+
"@release-it/conventional-changelog": "^5.0.0",
|
|
60
|
+
"@types/jest": "^29.5.5",
|
|
61
|
+
"@types/react": "^18.2.44",
|
|
62
|
+
"commitlint": "^17.0.2",
|
|
63
|
+
"del-cli": "^5.1.0",
|
|
64
|
+
"eslint": "^8.51.0",
|
|
65
|
+
"eslint-config-prettier": "^9.0.0",
|
|
66
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
67
|
+
"jest": "^29.7.0",
|
|
68
|
+
"prettier": "^3.0.3",
|
|
69
|
+
"react": "18.2.0",
|
|
70
|
+
"react-native": "0.73.5",
|
|
71
|
+
"react-native-builder-bob": "^0.20.0",
|
|
72
|
+
"release-it": "^15.0.0",
|
|
73
|
+
"turbo": "^1.10.7",
|
|
74
|
+
"typescript": "^5.2.2"
|
|
75
|
+
},
|
|
76
|
+
"resolutions": {
|
|
77
|
+
"@types/react": "^18.2.44"
|
|
78
|
+
},
|
|
79
|
+
"peerDependencies": {
|
|
80
|
+
"react": "*",
|
|
81
|
+
"react-native": "*"
|
|
82
|
+
},
|
|
83
|
+
"workspaces": [
|
|
84
|
+
"example"
|
|
85
|
+
],
|
|
86
|
+
"packageManager": "yarn@3.6.1",
|
|
87
|
+
"jest": {
|
|
88
|
+
"preset": "react-native",
|
|
89
|
+
"modulePathIgnorePatterns": [
|
|
90
|
+
"<rootDir>/example/node_modules",
|
|
91
|
+
"<rootDir>/lib/"
|
|
92
|
+
]
|
|
93
|
+
},
|
|
94
|
+
"commitlint": {
|
|
95
|
+
"extends": [
|
|
96
|
+
"@commitlint/config-conventional"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"release-it": {
|
|
100
|
+
"git": {
|
|
101
|
+
"commitMessage": "chore: release ${version}",
|
|
102
|
+
"tagName": "v${version}"
|
|
103
|
+
},
|
|
104
|
+
"npm": {
|
|
105
|
+
"publish": true
|
|
106
|
+
},
|
|
107
|
+
"github": {
|
|
108
|
+
"release": true
|
|
109
|
+
},
|
|
110
|
+
"plugins": {
|
|
111
|
+
"@release-it/conventional-changelog": {
|
|
112
|
+
"preset": "angular"
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"eslintConfig": {
|
|
117
|
+
"root": true,
|
|
118
|
+
"extends": [
|
|
119
|
+
"@react-native",
|
|
120
|
+
"prettier"
|
|
121
|
+
],
|
|
122
|
+
"rules": {
|
|
123
|
+
"prettier/prettier": [
|
|
124
|
+
"error",
|
|
125
|
+
{
|
|
126
|
+
"quoteProps": "consistent",
|
|
127
|
+
"singleQuote": true,
|
|
128
|
+
"tabWidth": 2,
|
|
129
|
+
"trailingComma": "es5",
|
|
130
|
+
"useTabs": false
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
"eslintIgnore": [
|
|
136
|
+
"node_modules/",
|
|
137
|
+
"lib/"
|
|
138
|
+
],
|
|
139
|
+
"prettier": {
|
|
140
|
+
"quoteProps": "consistent",
|
|
141
|
+
"singleQuote": true,
|
|
142
|
+
"tabWidth": 2,
|
|
143
|
+
"trailingComma": "es5",
|
|
144
|
+
"useTabs": false
|
|
145
|
+
},
|
|
146
|
+
"react-native-builder-bob": {
|
|
147
|
+
"source": "src",
|
|
148
|
+
"output": "lib",
|
|
149
|
+
"targets": [
|
|
150
|
+
"commonjs",
|
|
151
|
+
"module",
|
|
152
|
+
[
|
|
153
|
+
"typescript",
|
|
154
|
+
{
|
|
155
|
+
"project": "tsconfig.build.json"
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
|
+
|
|
6
|
+
Pod::Spec.new do |s|
|
|
7
|
+
s.name = "replate-camera"
|
|
8
|
+
s.version = package["version"]
|
|
9
|
+
s.summary = package["description"]
|
|
10
|
+
s.homepage = package["homepage"]
|
|
11
|
+
s.license = package["license"]
|
|
12
|
+
s.authors = package["author"]
|
|
13
|
+
|
|
14
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
15
|
+
s.source = { :git => "https://github.com/ReplateItaly/replate-camera.git", :tag => "#{s.version}" }
|
|
16
|
+
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
18
|
+
|
|
19
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
20
|
+
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
21
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
22
|
+
install_modules_dependencies(s)
|
|
23
|
+
else
|
|
24
|
+
s.dependency "React-Core"
|
|
25
|
+
|
|
26
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
27
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
28
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
29
|
+
s.pod_target_xcconfig = {
|
|
30
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
31
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
32
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
33
|
+
}
|
|
34
|
+
s.dependency "React-RCTFabric"
|
|
35
|
+
s.dependency "React-Codegen"
|
|
36
|
+
s.dependency "RCT-Folly"
|
|
37
|
+
s.dependency "RCTRequired"
|
|
38
|
+
s.dependency "RCTTypeSafety"
|
|
39
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {
|
|
2
|
+
requireNativeComponent,
|
|
3
|
+
UIManager,
|
|
4
|
+
Platform,
|
|
5
|
+
type ViewStyle,
|
|
6
|
+
NativeModules,
|
|
7
|
+
} from 'react-native';
|
|
8
|
+
|
|
9
|
+
const LINKING_ERROR =
|
|
10
|
+
`The package 'replate-camera' doesn't seem to be linked. Make sure: \n\n` +
|
|
11
|
+
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
|
|
12
|
+
'- You rebuilt the app after installing the package\n' +
|
|
13
|
+
'- You are not using Expo Go\n';
|
|
14
|
+
|
|
15
|
+
type ReplateCameraProps = {
|
|
16
|
+
// rect: Object;
|
|
17
|
+
color: string;
|
|
18
|
+
style: ViewStyle;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const ComponentName = 'ReplateCameraView';
|
|
22
|
+
|
|
23
|
+
export const ReplateCameraView =
|
|
24
|
+
UIManager.getViewManagerConfig(ComponentName) != null
|
|
25
|
+
? requireNativeComponent<ReplateCameraProps>(ComponentName)
|
|
26
|
+
: () => {
|
|
27
|
+
throw new Error(LINKING_ERROR);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const ReplateCameraModule = NativeModules.ReplateCameraController
|
|
31
|
+
? NativeModules.ReplateCameraController
|
|
32
|
+
: new Proxy(
|
|
33
|
+
{},
|
|
34
|
+
{
|
|
35
|
+
get() {
|
|
36
|
+
throw new Error(LINKING_ERROR);
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
export function takePhoto(): Promise<string> {
|
|
42
|
+
return ReplateCameraModule.takePhoto();
|
|
43
|
+
}
|