@azzapp/react-native-snapshot-view 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 +39 -0
- package/android/build.gradle +126 -0
- package/android/generated/java/com/azzapp/rnsnapshotview/NativeRNSnapshotViewSpec.java +42 -0
- package/android/generated/java/com/facebook/react/viewmanagers/RNSnapshotRendererManagerDelegate.java +31 -0
- package/android/generated/java/com/facebook/react/viewmanagers/RNSnapshotRendererManagerInterface.java +17 -0
- package/android/generated/jni/CMakeLists.txt +49 -0
- package/android/generated/jni/RNSnapshotViewSpec-generated.cpp +38 -0
- package/android/generated/jni/RNSnapshotViewSpec.h +31 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/ComponentDescriptors.cpp +22 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/ComponentDescriptors.h +24 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/EventEmitters.cpp +16 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/EventEmitters.h +23 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/Props.cpp +25 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/Props.h +27 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/RNSnapshotViewSpecJSI-generated.cpp +34 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/RNSnapshotViewSpecJSI.h +76 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/ShadowNodes.cpp +17 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/ShadowNodes.h +32 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/States.cpp +16 -0
- package/android/generated/jni/react/renderer/components/RNSnapshotViewSpec/States.h +29 -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/azzapp/rnsnapshotview/RNSnapshotRenderer.kt +27 -0
- package/android/src/main/java/com/azzapp/rnsnapshotview/RNSnapshotRendererManager.kt +28 -0
- package/android/src/main/java/com/azzapp/rnsnapshotview/ReactNativeSnapshotViewModule.kt +222 -0
- package/android/src/main/java/com/azzapp/rnsnapshotview/ReactNativeSnapshotViewPackage.kt +42 -0
- package/android/src/newarch/RNSnapshotRendererManagerSpec.kt +21 -0
- package/android/src/newarch/RNSnapshotViewSpec.kt +7 -0
- package/android/src/oldarch/RNSnapshotRendererManagerSpec.kt +9 -0
- package/android/src/oldarch/RNSnapshotViewSpec.kt +12 -0
- package/azzapp-react-native-snapshot-view.podspec +42 -0
- package/ios/RNSnapshotRenderer.h +17 -0
- package/ios/RNSnapshotRenderer.mm +61 -0
- package/ios/RNSnapshotRendererManager.mm +62 -0
- package/ios/RNSnapshotView.h +15 -0
- package/ios/RNSnapshotView.mm +71 -0
- package/ios/generated/RNSnapshotViewSpec/ComponentDescriptors.cpp +22 -0
- package/ios/generated/RNSnapshotViewSpec/ComponentDescriptors.h +24 -0
- package/ios/generated/RNSnapshotViewSpec/EventEmitters.cpp +16 -0
- package/ios/generated/RNSnapshotViewSpec/EventEmitters.h +23 -0
- package/ios/generated/RNSnapshotViewSpec/Props.cpp +25 -0
- package/ios/generated/RNSnapshotViewSpec/Props.h +27 -0
- package/ios/generated/RNSnapshotViewSpec/RCTComponentViewHelpers.h +20 -0
- package/ios/generated/RNSnapshotViewSpec/RNSnapshotViewSpec-generated.mm +36 -0
- package/ios/generated/RNSnapshotViewSpec/RNSnapshotViewSpec.h +54 -0
- package/ios/generated/RNSnapshotViewSpec/ShadowNodes.cpp +17 -0
- package/ios/generated/RNSnapshotViewSpec/ShadowNodes.h +32 -0
- package/ios/generated/RNSnapshotViewSpec/States.cpp +16 -0
- package/ios/generated/RNSnapshotViewSpec/States.h +29 -0
- package/ios/generated/RNSnapshotViewSpecJSI-generated.cpp +34 -0
- package/ios/generated/RNSnapshotViewSpecJSI.h +76 -0
- package/lib/commonjs/NativeRNSnapshotView.js +9 -0
- package/lib/commonjs/NativeRNSnapshotView.js.map +1 -0
- package/lib/commonjs/RNSnapshotRendererNativeComponent.js +10 -0
- package/lib/commonjs/RNSnapshotRendererNativeComponent.js.map +1 -0
- package/lib/commonjs/SnapshotRenderer.js +36 -0
- package/lib/commonjs/SnapshotRenderer.js.map +1 -0
- package/lib/commonjs/index.js +54 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/NativeRNSnapshotView.js +5 -0
- package/lib/module/NativeRNSnapshotView.js.map +1 -0
- package/lib/module/RNSnapshotRendererNativeComponent.js +5 -0
- package/lib/module/RNSnapshotRendererNativeComponent.js.map +1 -0
- package/lib/module/SnapshotRenderer.js +31 -0
- package/lib/module/SnapshotRenderer.js.map +1 -0
- package/lib/module/index.js +42 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/NativeRNSnapshotView.d.ts +8 -0
- package/lib/typescript/commonjs/src/NativeRNSnapshotView.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/RNSnapshotRendererNativeComponent.d.ts +7 -0
- package/lib/typescript/commonjs/src/RNSnapshotRendererNativeComponent.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/SnapshotRenderer.d.ts +27 -0
- package/lib/typescript/commonjs/src/SnapshotRenderer.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +16 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/NativeRNSnapshotView.d.ts +8 -0
- package/lib/typescript/module/src/NativeRNSnapshotView.d.ts.map +1 -0
- package/lib/typescript/module/src/RNSnapshotRendererNativeComponent.d.ts +7 -0
- package/lib/typescript/module/src/RNSnapshotRendererNativeComponent.d.ts.map +1 -0
- package/lib/typescript/module/src/SnapshotRenderer.d.ts +27 -0
- package/lib/typescript/module/src/SnapshotRenderer.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +16 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +202 -0
- package/src/NativeRNSnapshotView.ts +9 -0
- package/src/RNSnapshotRendererNativeComponent.ts +8 -0
- package/src/SnapshotRenderer.tsx +44 -0
- package/src/index.tsx +57 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateShadowNodeH.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
#pragma once
|
|
12
|
+
|
|
13
|
+
#include "EventEmitters.h"
|
|
14
|
+
#include "Props.h"
|
|
15
|
+
#include "States.h"
|
|
16
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
17
|
+
#include <jsi/jsi.h>
|
|
18
|
+
|
|
19
|
+
namespace facebook::react {
|
|
20
|
+
|
|
21
|
+
JSI_EXPORT extern const char RNSnapshotRendererComponentName[];
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* `ShadowNode` for <RNSnapshotRenderer> component.
|
|
25
|
+
*/
|
|
26
|
+
using RNSnapshotRendererShadowNode = ConcreteViewShadowNode<
|
|
27
|
+
RNSnapshotRendererComponentName,
|
|
28
|
+
RNSnapshotRendererProps,
|
|
29
|
+
RNSnapshotRendererEventEmitter,
|
|
30
|
+
RNSnapshotRendererState>;
|
|
31
|
+
|
|
32
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
4
|
+
*
|
|
5
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
6
|
+
* once the code is regenerated.
|
|
7
|
+
*
|
|
8
|
+
* @generated by codegen project: GenerateStateCpp.js
|
|
9
|
+
*/
|
|
10
|
+
#include "States.h"
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
|
|
3
|
+
*
|
|
4
|
+
* Do not edit this file as changes may cause incorrect behavior and will be lost
|
|
5
|
+
* once the code is regenerated.
|
|
6
|
+
*
|
|
7
|
+
* @generated by codegen project: GenerateStateH.js
|
|
8
|
+
*/
|
|
9
|
+
#pragma once
|
|
10
|
+
|
|
11
|
+
#ifdef ANDROID
|
|
12
|
+
#include <folly/dynamic.h>
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
namespace facebook::react {
|
|
16
|
+
|
|
17
|
+
class RNSnapshotRendererState {
|
|
18
|
+
public:
|
|
19
|
+
RNSnapshotRendererState() = default;
|
|
20
|
+
|
|
21
|
+
#ifdef ANDROID
|
|
22
|
+
RNSnapshotRendererState(RNSnapshotRendererState const &previousState, folly::dynamic data){};
|
|
23
|
+
folly::dynamic getDynamic() const {
|
|
24
|
+
return {};
|
|
25
|
+
};
|
|
26
|
+
#endif
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
} // namespace facebook::react
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.util.AttributeSet
|
|
5
|
+
import androidx.appcompat.widget.AppCompatImageView
|
|
6
|
+
|
|
7
|
+
class RNSnapshotRenderer : AppCompatImageView {
|
|
8
|
+
constructor(context: Context) : super(context)
|
|
9
|
+
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
|
10
|
+
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
11
|
+
context,
|
|
12
|
+
attrs,
|
|
13
|
+
defStyleAttr
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
private var _snapshotID: String? = null
|
|
17
|
+
fun setSnapshotID(snapshotID: String?) {
|
|
18
|
+
if (snapshotID != this._snapshotID) {
|
|
19
|
+
this._snapshotID = snapshotID
|
|
20
|
+
if (snapshotID == null) {
|
|
21
|
+
this.setImageBitmap(null)
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
this.setImageBitmap(ReactNativeSnapshotViewModule.getSnapShotMap()[snapshotID])
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
import android.graphics.Color
|
|
5
|
+
import com.facebook.react.module.annotations.ReactModule
|
|
6
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
7
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
8
|
+
|
|
9
|
+
@ReactModule(name = RNSnapshotRendererManager.NAME)
|
|
10
|
+
class RNSnapshotRendererManager :
|
|
11
|
+
RNSnapshotRendererManagerSpec<RNSnapshotRenderer>() {
|
|
12
|
+
override fun getName(): String {
|
|
13
|
+
return NAME
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public override fun createViewInstance(context: ThemedReactContext): RNSnapshotRenderer {
|
|
17
|
+
return RNSnapshotRenderer(context)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@ReactProp(name = "snapshotID")
|
|
21
|
+
override fun setSnapshotID(view: RNSnapshotRenderer?, snapshotID: String?) {
|
|
22
|
+
view?.setSnapshotID(snapshotID)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
companion object {
|
|
26
|
+
const val NAME = "RNSnapshotRenderer"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
import android.graphics.Canvas
|
|
5
|
+
import android.graphics.Matrix
|
|
6
|
+
import android.graphics.Paint
|
|
7
|
+
import android.os.Build
|
|
8
|
+
import android.os.Handler
|
|
9
|
+
import android.os.Looper
|
|
10
|
+
import android.util.Log
|
|
11
|
+
import android.view.PixelCopy
|
|
12
|
+
import android.view.SurfaceView
|
|
13
|
+
import android.view.TextureView
|
|
14
|
+
import android.view.View
|
|
15
|
+
import android.view.View.VISIBLE
|
|
16
|
+
import android.view.ViewGroup
|
|
17
|
+
import com.facebook.react.bridge.Promise
|
|
18
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
19
|
+
import com.facebook.react.bridge.ReactMethod
|
|
20
|
+
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
21
|
+
import com.facebook.react.fabric.FabricUIManager
|
|
22
|
+
import com.facebook.react.uimanager.NativeViewHierarchyManager
|
|
23
|
+
import com.facebook.react.uimanager.UIBlock
|
|
24
|
+
import com.facebook.react.uimanager.UIManagerHelper
|
|
25
|
+
import com.facebook.react.uimanager.UIManagerModule
|
|
26
|
+
import com.facebook.react.uimanager.common.UIManagerType
|
|
27
|
+
import java.util.Collections
|
|
28
|
+
import java.util.LinkedList
|
|
29
|
+
import java.util.UUID
|
|
30
|
+
import java.util.concurrent.CountDownLatch
|
|
31
|
+
import java.util.concurrent.TimeUnit
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ReactNativeSnapshotViewModule internal constructor(context: ReactApplicationContext) :
|
|
35
|
+
RNSnapshotViewSpec(context) {
|
|
36
|
+
|
|
37
|
+
override fun getName(): String {
|
|
38
|
+
return NAME
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@OptIn(UnstableReactNativeAPI::class)
|
|
42
|
+
@ReactMethod
|
|
43
|
+
override fun captureSnapshot(viewTag: Double, promise: Promise) {
|
|
44
|
+
|
|
45
|
+
val handleView = handleView@{ view: View? ->
|
|
46
|
+
if (view != null) {
|
|
47
|
+
val bitmap: Bitmap
|
|
48
|
+
try {
|
|
49
|
+
bitmap = getBitmapFromView(view)
|
|
50
|
+
} catch (e: Throwable) {
|
|
51
|
+
promise.reject("FAILED_TO_CREATE_BITMAP", e)
|
|
52
|
+
return@handleView
|
|
53
|
+
}
|
|
54
|
+
val uuid = UUID.randomUUID().toString()
|
|
55
|
+
snapshotMap[uuid] = bitmap;
|
|
56
|
+
promise.resolve(uuid)
|
|
57
|
+
} else {
|
|
58
|
+
promise.reject("not_found", "View not found")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
|
63
|
+
val uiManager = UIManagerHelper.getUIManager(reactApplicationContext, UIManagerType.FABRIC)
|
|
64
|
+
if (uiManager is FabricUIManager) {
|
|
65
|
+
uiManager.addUIBlock { uiBlockViewResolver ->
|
|
66
|
+
val view = uiBlockViewResolver.resolveView(viewTag.toInt())
|
|
67
|
+
handleView(view);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
promise.reject("not_found", "Cannot obtain UIManager")
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
val uiManager = reactApplicationContext.getNativeModule(
|
|
75
|
+
UIManagerModule::class.java
|
|
76
|
+
)
|
|
77
|
+
if (uiManager == null) {
|
|
78
|
+
promise.reject("not_found", "Cannot obtain UIManager")
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
uiManager.addUIBlock(UIBlock { nativeViewHierarchyManager: NativeViewHierarchyManager ->
|
|
82
|
+
val view = nativeViewHierarchyManager.resolveView(viewTag.toInt())
|
|
83
|
+
handleView(view)
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@ReactMethod
|
|
89
|
+
override fun releaseSnapshot(snapshotID: String, promise: Promise) {
|
|
90
|
+
snapshotMap.remove(snapshotID)
|
|
91
|
+
promise.resolve(null);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private fun getBitmapFromView(view: View): Bitmap {
|
|
95
|
+
val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
|
|
96
|
+
val canvas = Canvas(bitmap)
|
|
97
|
+
view.draw(canvas)
|
|
98
|
+
|
|
99
|
+
val childrenList = getAllChildren(view)
|
|
100
|
+
val paint = Paint()
|
|
101
|
+
paint.isAntiAlias = true
|
|
102
|
+
paint.isFilterBitmap = true
|
|
103
|
+
paint.isDither = true
|
|
104
|
+
|
|
105
|
+
for (child in childrenList) {
|
|
106
|
+
// Skip any child that we don't know how to process
|
|
107
|
+
if (child is TextureView) {
|
|
108
|
+
if (child.getVisibility() != VISIBLE) continue
|
|
109
|
+
child.isOpaque = false
|
|
110
|
+
val childBitmapBuffer = child.getBitmap(
|
|
111
|
+
Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888)
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
val countCanvasSave = canvas.save()
|
|
115
|
+
applyTransformations(canvas, view, child)
|
|
116
|
+
|
|
117
|
+
// Due to re-use of bitmaps for screenshot, we can get bitmap that is bigger in size than requested
|
|
118
|
+
canvas.drawBitmap(childBitmapBuffer, 0f, 0f, paint)
|
|
119
|
+
|
|
120
|
+
canvas.restoreToCount(countCanvasSave)
|
|
121
|
+
childBitmapBuffer.recycle()
|
|
122
|
+
} else if (child is SurfaceView) {
|
|
123
|
+
val latch = CountDownLatch(1)
|
|
124
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
125
|
+
val childBitmapBuffer = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888)
|
|
126
|
+
try {
|
|
127
|
+
PixelCopy.request(child, childBitmapBuffer, {
|
|
128
|
+
val countCanvasSave = canvas.save()
|
|
129
|
+
applyTransformations(canvas, view, child)
|
|
130
|
+
canvas.drawBitmap(childBitmapBuffer, 0f, 0f, paint)
|
|
131
|
+
canvas.restoreToCount(countCanvasSave)
|
|
132
|
+
latch.countDown()
|
|
133
|
+
}, Handler(Looper.getMainLooper()))
|
|
134
|
+
latch.await(SURFACE_VIEW_READ_PIXELS_TIMEOUT, TimeUnit.SECONDS)
|
|
135
|
+
} catch (e: Exception) {
|
|
136
|
+
Log.e(TAG, "Cannot PixelCopy for $child", e)
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
val cache = child.drawingCache
|
|
140
|
+
if (cache != null) {
|
|
141
|
+
canvas.drawBitmap(child.drawingCache, 0f, 0f, paint)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return bitmap
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
private fun getAllChildren(v: View): List<View> {
|
|
152
|
+
if (v !is ViewGroup) {
|
|
153
|
+
val viewArrayList = ArrayList<View>()
|
|
154
|
+
viewArrayList.add(v)
|
|
155
|
+
|
|
156
|
+
return viewArrayList
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
val result = ArrayList<View>()
|
|
160
|
+
|
|
161
|
+
for (i in 0 until v.childCount) {
|
|
162
|
+
val child: View = v.getChildAt(i)
|
|
163
|
+
|
|
164
|
+
// Do not add any parents, just add child elements
|
|
165
|
+
result.addAll(getAllChildren(child))
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return result
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Concat all the transformation matrix's from parent to child.
|
|
173
|
+
*/
|
|
174
|
+
private fun applyTransformations(c: Canvas, root: View, child: View): Matrix {
|
|
175
|
+
val transform: Matrix = Matrix()
|
|
176
|
+
val ms = LinkedList<View?>()
|
|
177
|
+
|
|
178
|
+
// Find all parents of the child view
|
|
179
|
+
var iterator = child
|
|
180
|
+
do {
|
|
181
|
+
ms.add(iterator)
|
|
182
|
+
|
|
183
|
+
iterator = iterator.parent as View
|
|
184
|
+
} while (iterator !== root)
|
|
185
|
+
|
|
186
|
+
// Apply transformations from parent --> child order
|
|
187
|
+
Collections.reverse(ms)
|
|
188
|
+
|
|
189
|
+
for (v in ms) {
|
|
190
|
+
if (v == null) {
|
|
191
|
+
continue
|
|
192
|
+
}
|
|
193
|
+
// Apply each view transformations, so each child will be affected by them
|
|
194
|
+
val dx = v.left + (if ((v !== child)) v.paddingLeft else 0) + v.translationX
|
|
195
|
+
val dy = v.top + (if ((v !== child)) v.paddingTop else 0) + v.translationY
|
|
196
|
+
c.translate(dx, dy)
|
|
197
|
+
transform.postTranslate(dx, dy)
|
|
198
|
+
|
|
199
|
+
c.rotate(v.rotation, v.pivotX, v.pivotY)
|
|
200
|
+
transform.postRotate(v.rotation, v.pivotX, v.pivotY)
|
|
201
|
+
|
|
202
|
+
c.scale(v.scaleX, v.scaleY, v.pivotX, v.pivotY)
|
|
203
|
+
transform.postScale(v.scaleX, v.scaleY, v.pivotX, v.pivotY)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return transform
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
companion object {
|
|
210
|
+
const val NAME = "RNSnapshotView"
|
|
211
|
+
|
|
212
|
+
const val TAG = "ReactNativeSnapshotView"
|
|
213
|
+
|
|
214
|
+
private val snapshotMap: MutableMap<String, Bitmap> = HashMap()
|
|
215
|
+
|
|
216
|
+
fun getSnapShotMap(): Map<String, Bitmap> {
|
|
217
|
+
return snapshotMap
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private const val SURFACE_VIEW_READ_PIXELS_TIMEOUT: Long = 5
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.TurboReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
|
+
import com.facebook.react.uimanager.ViewManager
|
|
9
|
+
import java.util.ArrayList
|
|
10
|
+
import java.util.HashMap
|
|
11
|
+
|
|
12
|
+
class ReactNativeSnapshotViewPackage : TurboReactPackage() {
|
|
13
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
14
|
+
return if (name == ReactNativeSnapshotViewModule.NAME) {
|
|
15
|
+
ReactNativeSnapshotViewModule(reactContext)
|
|
16
|
+
} else {
|
|
17
|
+
null
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
22
|
+
return ReactModuleInfoProvider {
|
|
23
|
+
val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
|
|
24
|
+
val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
|
|
25
|
+
moduleInfos[ReactNativeSnapshotViewModule.NAME] = ReactModuleInfo(
|
|
26
|
+
ReactNativeSnapshotViewModule.NAME,
|
|
27
|
+
ReactNativeSnapshotViewModule.NAME,
|
|
28
|
+
false, // canOverrideExistingModule
|
|
29
|
+
false, // needsEagerInit
|
|
30
|
+
true, // hasConstants
|
|
31
|
+
false, // isCxxModule
|
|
32
|
+
isTurboModule // isTurboModule
|
|
33
|
+
)
|
|
34
|
+
moduleInfos
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
|
|
38
|
+
val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
|
|
39
|
+
viewManagers.add(RNSnapshotRendererManager())
|
|
40
|
+
return viewManagers
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
7
|
+
import com.facebook.react.uimanager.ViewManagerDelegate
|
|
8
|
+
import com.facebook.react.viewmanagers.RNSnapshotRendererManagerDelegate
|
|
9
|
+
import com.facebook.react.viewmanagers.RNSnapshotRendererManagerInterface
|
|
10
|
+
|
|
11
|
+
abstract class RNSnapshotRendererManagerSpec<T : View> : SimpleViewManager<T>(), RNSnapshotRendererManagerInterface<T> {
|
|
12
|
+
private val mDelegate: ViewManagerDelegate<T>
|
|
13
|
+
|
|
14
|
+
init {
|
|
15
|
+
mDelegate = RNSnapshotRendererManagerDelegate(this)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
override fun getDelegate(): ViewManagerDelegate<T>? {
|
|
19
|
+
return mDelegate
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
import android.view.View
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
6
|
+
|
|
7
|
+
abstract class RNSnapshotRendererManagerSpec<T : View> : SimpleViewManager<T>() {
|
|
8
|
+
abstract fun setSnapshotID(view: T?, snapshodID: String?)
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
package com.azzapp.rnsnapshotview
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
4
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
|
|
7
|
+
abstract class RNSnapshotViewSpec internal constructor(context: ReactApplicationContext) :
|
|
8
|
+
ReactContextBaseJavaModule(context) {
|
|
9
|
+
|
|
10
|
+
abstract fun captureSnapshot(viewTag: Double, promise: Promise)
|
|
11
|
+
abstract fun releaseSnapshot(snapshotID: String, promise: Promise)
|
|
12
|
+
}
|
|
@@ -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 = "azzapp-react-native-snapshot-view"
|
|
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/AzzappApp/react-native-snapshot-view.git", :tag => "#{s.version}" }
|
|
16
|
+
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm,cpp}"
|
|
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
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// This guard prevent this file to be compiled in the old architecture.
|
|
2
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
3
|
+
#import <React/RCTViewComponentView.h>
|
|
4
|
+
#import <UIKit/UIKit.h>
|
|
5
|
+
|
|
6
|
+
#ifndef RNSnapshotRendererNativeComponent_h
|
|
7
|
+
#define RNSnapshotRendererNativeComponent_h
|
|
8
|
+
|
|
9
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
10
|
+
|
|
11
|
+
@interface RNSnapshotRenderer : RCTViewComponentView
|
|
12
|
+
@end
|
|
13
|
+
|
|
14
|
+
NS_ASSUME_NONNULL_END
|
|
15
|
+
|
|
16
|
+
#endif /* RNSnapshotRendererNativeComponent_h */
|
|
17
|
+
#endif /* RCT_NEW_ARCH_ENABLED */
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
#import "RNSnapshotRenderer.h"
|
|
3
|
+
|
|
4
|
+
#import "generated/RNSnapshotViewSpec/ComponentDescriptors.h"
|
|
5
|
+
#import "generated/RNSnapshotViewSpec/EventEmitters.h"
|
|
6
|
+
#import "generated/RNSnapshotViewSpec/Props.h"
|
|
7
|
+
#import "generated/RNSnapshotViewSpec/RCTComponentViewHelpers.h"
|
|
8
|
+
|
|
9
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
10
|
+
#import "RNSnapshotView.h"
|
|
11
|
+
|
|
12
|
+
using namespace facebook::react;
|
|
13
|
+
|
|
14
|
+
@interface RNSnapshotRenderer () <RCTRNSnapshotRendererViewProtocol>
|
|
15
|
+
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
@implementation RNSnapshotRenderer {
|
|
19
|
+
UIView * _view;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
23
|
+
{
|
|
24
|
+
return concreteComponentDescriptorProvider<RNSnapshotRendererComponentDescriptor>();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
28
|
+
{
|
|
29
|
+
if (self = [super initWithFrame:frame]) {
|
|
30
|
+
static const auto defaultProps = std::make_shared<const RNSnapshotRendererProps>();
|
|
31
|
+
_props = defaultProps;
|
|
32
|
+
|
|
33
|
+
_view = [[UIView alloc] init];
|
|
34
|
+
|
|
35
|
+
self.contentView = _view;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return self;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
42
|
+
{
|
|
43
|
+
const auto &oldViewProps = *std::static_pointer_cast<RNSnapshotRendererProps const>(_props);
|
|
44
|
+
const auto &newViewProps = *std::static_pointer_cast<RNSnapshotRendererProps const>(props);
|
|
45
|
+
|
|
46
|
+
if (oldViewProps.snapshotID != newViewProps.snapshotID) {
|
|
47
|
+
NSDictionary<NSString *, UIView *> *snapshotMap = [RNSnapshotView getSnapShotMap];
|
|
48
|
+
self.contentView = snapshotMap[[NSString stringWithCString:newViewProps.snapshotID.c_str()
|
|
49
|
+
encoding:[NSString defaultCStringEncoding]]];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
[super updateProps:props oldProps:oldProps];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
Class<RCTComponentViewProtocol> RNSnapshotRendererCls(void)
|
|
56
|
+
{
|
|
57
|
+
return RNSnapshotRenderer.class;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@end
|
|
61
|
+
#endif
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#ifndef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
#import <React/RCTViewManager.h>
|
|
3
|
+
#import <React/RCTUIManager.h>
|
|
4
|
+
#import "RCTBridge.h"
|
|
5
|
+
#import "Utils.h"
|
|
6
|
+
#import "RNSnapshotView.h"
|
|
7
|
+
|
|
8
|
+
@interface RNSnapshotRendererManager : RCTViewManager
|
|
9
|
+
@end
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@interface RNSnapshotRenderer : UIView
|
|
13
|
+
|
|
14
|
+
@property (nonatomic, strong) NSString *snapshotID;
|
|
15
|
+
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@implementation RNSnapshotRenderer
|
|
20
|
+
|
|
21
|
+
{
|
|
22
|
+
UIView *_snapshotView;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
-(void)setSnapshotID:(NSString *)snapshotID {
|
|
27
|
+
if (![snapshotID isEqualToString:_snapshotID]) {
|
|
28
|
+
_snapshotID = snapshotID;
|
|
29
|
+
if(_snapshotView) {
|
|
30
|
+
[_snapshotView removeFromSuperview];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
NSDictionary<NSString *, UIView *> *snapshotMap = [RNSnapshotView getSnapShotMap];
|
|
34
|
+
_snapshotView = snapshotMap[snapshotID];
|
|
35
|
+
if (_snapshotView != nil) {
|
|
36
|
+
self.autoresizesSubviews = YES;
|
|
37
|
+
_snapshotView.frame = self.bounds;
|
|
38
|
+
_snapshotView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
|
|
39
|
+
UIViewAutoresizingFlexibleHeight);
|
|
40
|
+
|
|
41
|
+
[self addSubview:_snapshotView];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@end
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@implementation RNSnapshotRendererManager
|
|
50
|
+
|
|
51
|
+
RCT_EXPORT_MODULE(RNSnapshotRenderer)
|
|
52
|
+
|
|
53
|
+
- (UIView *)view
|
|
54
|
+
{
|
|
55
|
+
return [[RNSnapshotRenderer alloc] init];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
RCT_EXPORT_VIEW_PROPERTY(snapshotID, NSString *)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@end
|
|
62
|
+
#endif
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
3
|
+
#import "RNSnapshotViewSpec.h"
|
|
4
|
+
|
|
5
|
+
@interface RNSnapshotView : NSObject <NativeRNSnapshotViewSpec>
|
|
6
|
+
#else
|
|
7
|
+
#import <React/RCTBridgeModule.h>
|
|
8
|
+
|
|
9
|
+
@interface RNSnapshotView : NSObject <RCTBridgeModule>
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
+(NSDictionary<NSString*, UIView *> *)getSnapShotMap;
|
|
14
|
+
|
|
15
|
+
@end
|