@azzapp/react-native-snapshot-view 0.1.4 → 0.3.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.
Files changed (41) hide show
  1. package/README.md +3 -2
  2. package/android/build.gradle +13 -59
  3. package/android/gradle.properties +5 -5
  4. package/android/src/main/AndroidManifest.xml +1 -2
  5. package/android/src/main/java/com/azzapp/rnsnapshotview/RNSnapshotRendererManager.kt +15 -4
  6. package/android/src/main/java/com/azzapp/rnsnapshotview/ReactNativeSnapshotViewModule.kt +54 -25
  7. package/android/src/main/java/com/azzapp/rnsnapshotview/ReactNativeSnapshotViewPackage.kt +2 -6
  8. package/azzapp-react-native-snapshot-view.podspec +2 -23
  9. package/ios/RNSnapshotRenderer.h +0 -3
  10. package/ios/RNSnapshotRenderer.mm +9 -6
  11. package/ios/RNSnapshotView.h +2 -8
  12. package/ios/RNSnapshotView.mm +85 -41
  13. package/lib/module/NativeRNSnapshotView.js.map +1 -1
  14. package/lib/module/RNSnapshotRendererNativeComponent.ts +7 -0
  15. package/lib/module/SnapshotRenderer.js +4 -5
  16. package/lib/module/SnapshotRenderer.js.map +1 -1
  17. package/lib/module/index.js +22 -15
  18. package/lib/module/index.js.map +1 -1
  19. package/lib/typescript/package.json +1 -0
  20. package/lib/typescript/src/NativeRNSnapshotView.d.ts +2 -0
  21. package/lib/typescript/src/NativeRNSnapshotView.d.ts.map +1 -1
  22. package/lib/typescript/src/RNSnapshotRendererNativeComponent.d.ts +2 -2
  23. package/lib/typescript/src/RNSnapshotRendererNativeComponent.d.ts.map +1 -1
  24. package/lib/typescript/src/SnapshotRenderer.d.ts +6 -14
  25. package/lib/typescript/src/SnapshotRenderer.d.ts.map +1 -1
  26. package/lib/typescript/src/index.d.ts +13 -0
  27. package/lib/typescript/src/index.d.ts.map +1 -1
  28. package/package.json +41 -53
  29. package/react-native.config.js +4 -0
  30. package/src/NativeRNSnapshotView.ts +2 -0
  31. package/src/RNSnapshotRendererNativeComponent.ts +1 -2
  32. package/src/SnapshotRenderer.tsx +9 -10
  33. package/src/index.tsx +21 -25
  34. package/android/src/main/AndroidManifestNew.xml +0 -2
  35. package/android/src/newarch/RNSnapshotRendererManagerSpec.kt +0 -21
  36. package/android/src/newarch/RNSnapshotViewSpec.kt +0 -7
  37. package/android/src/oldarch/RNSnapshotRendererManagerSpec.kt +0 -9
  38. package/android/src/oldarch/RNSnapshotViewSpec.kt +0 -12
  39. package/ios/RNSnapshotRendererManager.mm +0 -62
  40. package/lib/module/RNSnapshotRendererNativeComponent.js +0 -5
  41. package/lib/module/RNSnapshotRendererNativeComponent.js.map +0 -1
package/README.md CHANGED
@@ -25,10 +25,11 @@ const snapshotID = await captureSnapshot(viewRef.current);
25
25
 
26
26
  >:warning: captured snapshot are kept in memory, either use `releaseSnapshot` to release them, or let the `SnapshotRenderer` component release the snapshot on unmount.
27
27
 
28
-
29
28
  ## Contributing
30
29
 
31
- See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
30
+ - [Development workflow](CONTRIBUTING.md#development-workflow)
31
+ - [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
32
+ - [Code of conduct](CODE_OF_CONDUCT.md)
32
33
 
33
34
  ## License
34
35
 
@@ -1,6 +1,7 @@
1
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["ReactNativeSnapshotView_kotlinVersion"]
2
+ ext.getExtOrDefault = {name ->
3
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeSnapshotView_' + name]
4
+ }
4
5
 
5
6
  repositories {
6
7
  google()
@@ -8,63 +9,30 @@ buildscript {
8
9
  }
9
10
 
10
11
  dependencies {
11
- classpath "com.android.tools.build:gradle:7.2.1"
12
+ classpath "com.android.tools.build:gradle:8.7.2"
12
13
  // noinspection DifferentKotlinGradleVersion
13
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}"
14
15
  }
15
16
  }
16
17
 
17
- def reactNativeArchitectures() {
18
- def value = rootProject.getProperties().get("reactNativeArchitectures")
19
- return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
20
- }
21
-
22
- def isNewArchitectureEnabled() {
23
- return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
24
- }
25
18
 
26
19
  apply plugin: "com.android.library"
27
20
  apply plugin: "kotlin-android"
28
21
 
29
- if (isNewArchitectureEnabled()) {
30
- apply plugin: "com.facebook.react"
31
- }
32
-
33
- def getExtOrDefault(name) {
34
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ReactNativeSnapshotView_" + name]
35
- }
22
+ apply plugin: "com.facebook.react"
36
23
 
37
24
  def getExtOrIntegerDefault(name) {
38
- return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeSnapshotView_" + name]).toInteger()
39
- }
40
-
41
- def supportsNamespace() {
42
- def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
43
- def major = parsed[0].toInteger()
44
- def minor = parsed[1].toInteger()
45
-
46
- // Namespace support was added in 7.3.0
47
- return (major == 7 && minor >= 3) || major >= 8
25
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["SnapshotView_" + name]).toInteger()
48
26
  }
49
27
 
50
28
  android {
51
- if (supportsNamespace()) {
52
- namespace "com.azzapp.rnsnapshotview"
53
-
54
- sourceSets {
55
- main {
56
- manifest.srcFile "src/main/AndroidManifestNew.xml"
57
- }
58
- }
59
- }
29
+ namespace "com.azzapp.rnsnapshotview"
60
30
 
61
31
  compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
62
32
 
63
33
  defaultConfig {
64
34
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
65
35
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
66
- buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
67
-
68
36
  }
69
37
 
70
38
  buildFeatures {
@@ -88,13 +56,10 @@ android {
88
56
 
89
57
  sourceSets {
90
58
  main {
91
- if (isNewArchitectureEnabled()) {
92
- java.srcDirs += [
93
- "src/newarch",
94
- ]
95
- } else {
96
- java.srcDirs += ["src/oldarch"]
97
- }
59
+ java.srcDirs += [
60
+ "generated/java",
61
+ "generated/jni"
62
+ ]
98
63
  }
99
64
  }
100
65
  }
@@ -107,17 +72,6 @@ repositories {
107
72
  def kotlin_version = getExtOrDefault("kotlinVersion")
108
73
 
109
74
  dependencies {
110
- // For < 0.71, this will be from the local maven repo
111
- // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
112
- //noinspection GradleDynamicVersion
113
- implementation "com.facebook.react:react-native:+"
75
+ implementation "com.facebook.react:react-android"
114
76
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
115
77
  }
116
-
117
- if (isNewArchitectureEnabled()) {
118
- react {
119
- jsRootDir = file("../src/")
120
- libraryName = "ReactNativeSnapshotViewView"
121
- codegenJavaPackageName = "com.azzapp.rnsnapshotview"
122
- }
123
- }
@@ -1,5 +1,5 @@
1
- ReactNativeSnapshotView_kotlinVersion=1.7.0
2
- ReactNativeSnapshotView_minSdkVersion=21
3
- ReactNativeSnapshotView_targetSdkVersion=31
4
- ReactNativeSnapshotView_compileSdkVersion=31
5
- ReactNativeSnapshotView_ndkversion=21.4.7075529
1
+ ReactNativeSnapshotView_kotlinVersion=2.0.21
2
+ ReactNativeSnapshotView_minSdkVersion=24
3
+ ReactNativeSnapshotView_targetSdkVersion=34
4
+ ReactNativeSnapshotView_compileSdkVersion=35
5
+ ReactNativeSnapshotView_ndkVersion=27.1.12297006
@@ -1,3 +1,2 @@
1
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
- package="com.azzapp.rnsnapshotview">
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
3
2
  </manifest>
@@ -1,14 +1,25 @@
1
1
  package com.azzapp.rnsnapshotview
2
2
 
3
-
4
- import android.graphics.Color
5
3
  import com.facebook.react.module.annotations.ReactModule
4
+ import com.facebook.react.uimanager.SimpleViewManager
6
5
  import com.facebook.react.uimanager.ThemedReactContext
6
+ import com.facebook.react.uimanager.ViewManagerDelegate
7
7
  import com.facebook.react.uimanager.annotations.ReactProp
8
+ import com.facebook.react.viewmanagers.RNSnapshotRendererManagerInterface
9
+ import com.facebook.react.viewmanagers.RNSnapshotRendererManagerDelegate
8
10
 
9
11
  @ReactModule(name = RNSnapshotRendererManager.NAME)
10
- class RNSnapshotRendererManager :
11
- RNSnapshotRendererManagerSpec<RNSnapshotRenderer>() {
12
+ class RNSnapshotRendererManager : SimpleViewManager<RNSnapshotRenderer>(),
13
+ RNSnapshotRendererManagerInterface<RNSnapshotRenderer> {
14
+ private val mDelegate: ViewManagerDelegate<RNSnapshotRenderer>
15
+ init {
16
+ mDelegate = RNSnapshotRendererManagerDelegate(this)
17
+ }
18
+
19
+ override fun getDelegate(): ViewManagerDelegate<RNSnapshotRenderer>? {
20
+ return mDelegate
21
+ }
22
+
12
23
  override fun getName(): String {
13
24
  return NAME
14
25
  }
@@ -19,10 +19,7 @@ import com.facebook.react.bridge.ReactApplicationContext
19
19
  import com.facebook.react.bridge.ReactMethod
20
20
  import com.facebook.react.common.annotations.UnstableReactNativeAPI
21
21
  import com.facebook.react.fabric.FabricUIManager
22
- import com.facebook.react.uimanager.NativeViewHierarchyManager
23
- import com.facebook.react.uimanager.UIBlock
24
22
  import com.facebook.react.uimanager.UIManagerHelper
25
- import com.facebook.react.uimanager.UIManagerModule
26
23
  import com.facebook.react.uimanager.common.UIManagerType
27
24
  import java.util.Collections
28
25
  import java.util.LinkedList
@@ -32,7 +29,7 @@ import java.util.concurrent.TimeUnit
32
29
 
33
30
 
34
31
  class ReactNativeSnapshotViewModule internal constructor(context: ReactApplicationContext) :
35
- RNSnapshotViewSpec(context) {
32
+ NativeRNSnapshotViewSpec(context) {
36
33
 
37
34
  override fun getName(): String {
38
35
  return NAME
@@ -59,30 +56,62 @@ class ReactNativeSnapshotViewModule internal constructor(context: ReactApplicati
59
56
  }
60
57
  }
61
58
 
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);
59
+ val uiManager = UIManagerHelper.getUIManager(reactApplicationContext, UIManagerType.FABRIC)
60
+ if (uiManager !is FabricUIManager) {
61
+ promise.reject("not_found", "Cannot obtain UIManager")
62
+ return
63
+ }
64
+
65
+ uiManager.addUIBlock { uiBlockViewResolver ->
66
+ val view = uiBlockViewResolver.resolveView(viewTag.toInt())
67
+ handleView(view)
68
+ }
69
+ }
70
+
71
+ @ReactMethod
72
+ override fun snapshotScreen(promise: Promise) {
73
+ val activity = reactApplicationContext.currentActivity
74
+ if (activity == null) {
75
+ promise.reject("not_found", "Activity not found")
76
+ return
77
+ }
78
+ val window = activity.window
79
+ if (window == null) {
80
+ promise.reject("not_found", "Window not found")
81
+ return
82
+ }
83
+ val decorView = window.decorView
84
+ val bitmap = Bitmap.createBitmap(decorView.width, decorView.height, Bitmap.Config.ARGB_8888)
85
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
86
+ PixelCopy.request(window, bitmap, { result ->
87
+ if (result == PixelCopy.SUCCESS) {
88
+ val uuid = UUID.randomUUID().toString()
89
+ snapshotMap[uuid] = bitmap
90
+ promise.resolve(uuid)
91
+ } else {
92
+ bitmap.recycle()
93
+ promise.reject("snapshot_failed", "PixelCopy failed with result $result")
68
94
  }
69
- } else {
70
- promise.reject("not_found", "Cannot obtain UIManager")
71
- return
72
- }
95
+ }, Handler(Looper.getMainLooper()))
73
96
  } 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
- })
97
+ decorView.draw(Canvas(bitmap))
98
+ val uuid = UUID.randomUUID().toString()
99
+ snapshotMap[uuid] = bitmap
100
+ promise.resolve(uuid)
101
+ }
102
+ }
103
+
104
+ @ReactMethod
105
+ override fun duplicateSnapshot(snapshotID: String, promise: Promise) {
106
+ val original = snapshotMap[snapshotID]
107
+ if (original == null) {
108
+ promise.reject("not_found", "Snapshot not found")
109
+ return
85
110
  }
111
+ val copy = original.copy(original.config ?: Bitmap.Config.ARGB_8888, false)
112
+ val uuid = UUID.randomUUID().toString()
113
+ snapshotMap[uuid] = copy
114
+ promise.resolve(uuid)
86
115
  }
87
116
 
88
117
  @ReactMethod
@@ -6,7 +6,6 @@ import com.facebook.react.bridge.ReactApplicationContext
6
6
  import com.facebook.react.module.model.ReactModuleInfo
7
7
  import com.facebook.react.module.model.ReactModuleInfoProvider
8
8
  import com.facebook.react.uimanager.ViewManager
9
- import java.util.ArrayList
10
9
  import java.util.HashMap
11
10
 
12
11
  class ReactNativeSnapshotViewPackage : TurboReactPackage() {
@@ -21,7 +20,6 @@ class ReactNativeSnapshotViewPackage : TurboReactPackage() {
21
20
  override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
22
21
  return ReactModuleInfoProvider {
23
22
  val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
24
- val isTurboModule: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
25
23
  moduleInfos[ReactNativeSnapshotViewModule.NAME] = ReactModuleInfo(
26
24
  ReactNativeSnapshotViewModule.NAME,
27
25
  ReactNativeSnapshotViewModule.NAME,
@@ -29,14 +27,12 @@ class ReactNativeSnapshotViewPackage : TurboReactPackage() {
29
27
  false, // needsEagerInit
30
28
  true, // hasConstants
31
29
  false, // isCxxModule
32
- isTurboModule // isTurboModule
30
+ true // isTurboModule
33
31
  )
34
32
  moduleInfos
35
33
  }
36
34
  }
37
35
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
38
- val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
39
- viewManagers.add(RNSnapshotRendererManager())
40
- return viewManagers
36
+ return listOf(RNSnapshotRendererManager())
41
37
  }
42
38
  }
@@ -1,7 +1,6 @@
1
1
  require "json"
2
2
 
3
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
4
 
6
5
  Pod::Spec.new do |s|
7
6
  s.name = "azzapp-react-native-snapshot-view"
@@ -15,28 +14,8 @@ Pod::Spec.new do |s|
15
14
  s.source = { :git => "https://github.com/AzzappApp/react-native-snapshot-view.git", :tag => "#{s.version}" }
16
15
 
17
16
  s.source_files = "ios/**/*.{h,m,mm,cpp}"
17
+ s.private_header_files = "ios/**/*.h"
18
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
19
 
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
20
+ install_modules_dependencies(s)
42
21
  end
@@ -1,5 +1,3 @@
1
- // This guard prevent this file to be compiled in the old architecture.
2
- #ifdef RCT_NEW_ARCH_ENABLED
3
1
  #import <React/RCTViewComponentView.h>
4
2
  #import <UIKit/UIKit.h>
5
3
 
@@ -14,4 +12,3 @@ NS_ASSUME_NONNULL_BEGIN
14
12
  NS_ASSUME_NONNULL_END
15
13
 
16
14
  #endif /* RNSnapshotRendererNativeComponent_h */
17
- #endif /* RCT_NEW_ARCH_ENABLED */
@@ -1,4 +1,3 @@
1
- #ifdef RCT_NEW_ARCH_ENABLED
2
1
  #import "RNSnapshotRenderer.h"
3
2
 
4
3
  #import <react/renderer/components/RNSnapshotViewSpec/ComponentDescriptors.h>
@@ -44,9 +43,14 @@ using namespace facebook::react;
44
43
  const auto &newViewProps = *std::static_pointer_cast<RNSnapshotRendererProps const>(props);
45
44
 
46
45
  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]]];
46
+ NSString *identifier = [NSString stringWithUTF8String:newViewProps.snapshotID.c_str()];
47
+ if (identifier.length == 0) {
48
+ self.contentView = nil;
49
+ } else {
50
+ UIView *snapshot = [RNSnapshotView getSnapShotMap][identifier];
51
+ [snapshot removeFromSuperview];
52
+ self.contentView = snapshot;
53
+ }
50
54
  }
51
55
 
52
56
  [super updateProps:props oldProps:oldProps];
@@ -57,5 +61,4 @@ Class<RCTComponentViewProtocol> RNSnapshotRendererCls(void)
57
61
  return RNSnapshotRenderer.class;
58
62
  }
59
63
 
60
- @end
61
- #endif
64
+ @end
@@ -1,15 +1,9 @@
1
1
 
2
- #ifdef RCT_NEW_ARCH_ENABLED
3
2
  #import "RNSnapshotViewSpec.h"
3
+ #import <UIKit/UIKit.h>
4
4
 
5
5
  @interface RNSnapshotView : NSObject <NativeRNSnapshotViewSpec>
6
- #else
7
- #import <React/RCTBridgeModule.h>
8
6
 
9
- @interface RNSnapshotView : NSObject <RCTBridgeModule>
10
- #endif
11
-
12
-
13
- +(NSDictionary<NSString*, UIView *> *)getSnapShotMap;
7
+ + (NSMutableDictionary<NSString *, UIView *> *)getSnapShotMap;
14
8
 
15
9
  @end
@@ -1,71 +1,115 @@
1
1
  #import "RNSnapshotView.h"
2
- #import <React/RCTUIManager.h>
3
- #if __has_include(<React/RCTUIManagerUtils.h>)
4
- #import <React/RCTUIManagerUtils.h>
5
- #endif
2
+
6
3
  #import <React/RCTBridge.h>
4
+ #import <React/RCTBridge+Private.h>
5
+ #import <React/RCTUIManager.h>
7
6
 
8
7
  @implementation RNSnapshotView
9
8
  RCT_EXPORT_MODULE()
10
9
 
11
10
  @synthesize bridge = _bridge;
12
11
 
13
- - (dispatch_queue_t)methodQueue
14
- {
15
- return RCTGetUIManagerQueue();
16
- }
17
-
18
- static NSMutableDictionary<NSString*, UIView *> *snapshotMap;
12
+ static NSMutableDictionary<NSString *, UIView *> *snapshotMap;
19
13
 
20
- +(NSDictionary<NSString *,UIView *> *)getSnapShotMap {
14
+ + (NSMutableDictionary<NSString *, UIView *> *)getSnapShotMap
15
+ {
21
16
  if (snapshotMap == nil) {
22
17
  snapshotMap = [[NSMutableDictionary alloc] init];
23
18
  }
24
19
  return snapshotMap;
25
20
  }
26
21
 
27
- RCT_EXPORT_METHOD(
28
- captureSnapshot: (double)viewTag
29
- resolve:(RCTPromiseResolveBlock)resolve
30
- reject:(RCTPromiseRejectBlock)reject) {
31
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
32
- UIView *view = viewRegistry[[NSNumber numberWithDouble:viewTag]];
33
- if (view != nil) {
34
- UIView *snapshot = [view snapshotViewAfterScreenUpdates:NO];
35
- if (snapshotMap == nil) {
36
- snapshotMap = [[NSMutableDictionary alloc] init];
37
- }
38
- NSUUID *uuid = [NSUUID UUID];
39
- NSString *str = [uuid UUIDString];
40
- [snapshotMap setValue:snapshot forKey:str];
41
- resolve(str);
42
- } else {
22
+ - (void)captureSnapshot:(double)viewTag
23
+ resolve:(RCTPromiseResolveBlock)resolve
24
+ reject:(RCTPromiseRejectBlock)reject
25
+ {
26
+ dispatch_async(dispatch_get_main_queue(), ^{
27
+ UIView *view = [self viewForReactTag:viewTag];
28
+ if (view == nil) {
43
29
  reject(@"not_found", @"View not found", nil);
30
+ return;
44
31
  }
45
- }];
32
+
33
+ UIView *snapshot = [view snapshotViewAfterScreenUpdates:NO];
34
+ if (snapshot == nil) {
35
+ reject(@"snapshot_failed", @"Failed to capture snapshot", nil);
36
+ return;
37
+ }
38
+
39
+ NSString *identifier = [[NSUUID UUID] UUIDString];
40
+ [[RNSnapshotView getSnapShotMap] setObject:snapshot forKey:identifier];
41
+ resolve(identifier);
42
+ });
46
43
  }
47
44
 
48
- RCT_EXPORT_METHOD(
49
- releaseSnapshot: (NSString *)uuid
50
- resolve:(RCTPromiseResolveBlock)resolve
51
- reject:(RCTPromiseRejectBlock)reject) {
45
+ - (void)snapshotScreen:(RCTPromiseResolveBlock)resolve
46
+ reject:(RCTPromiseRejectBlock)reject
47
+ {
48
+ dispatch_async(dispatch_get_main_queue(), ^{
49
+ UIWindow *window = [[UIApplication sharedApplication] keyWindow];
50
+ if (window == nil) {
51
+ reject(@"not_found", @"Key window not found", nil);
52
+ return;
53
+ }
54
+
55
+ UIView *snapshot = [window snapshotViewAfterScreenUpdates:NO];
56
+ if (snapshot == nil) {
57
+ reject(@"snapshot_failed", @"Failed to capture screen snapshot", nil);
58
+ return;
59
+ }
60
+
61
+ NSString *identifier = [[NSUUID UUID] UUIDString];
62
+ [[RNSnapshotView getSnapShotMap] setObject:snapshot forKey:identifier];
63
+ resolve(identifier);
64
+ });
65
+ }
66
+
67
+ - (void)duplicateSnapshot:(NSString *)snapshotID
68
+ resolve:(RCTPromiseResolveBlock)resolve
69
+ reject:(RCTPromiseRejectBlock)reject
70
+ {
71
+ dispatch_async(dispatch_get_main_queue(), ^{
72
+ UIView *original = [[RNSnapshotView getSnapShotMap] objectForKey:snapshotID];
73
+ if (original == nil) {
74
+ reject(@"not_found", @"Snapshot not found", nil);
75
+ return;
76
+ }
77
+
78
+ UIView *duplicate = [original snapshotViewAfterScreenUpdates:NO];
79
+ if (duplicate == nil) {
80
+ reject(@"snapshot_failed", @"Failed to duplicate snapshot", nil);
81
+ return;
82
+ }
83
+
84
+ NSString *identifier = [[NSUUID UUID] UUIDString];
85
+ [[RNSnapshotView getSnapShotMap] setObject:duplicate forKey:identifier];
86
+ resolve(identifier);
87
+ });
88
+ }
89
+
90
+ - (void)releaseSnapshot:(NSString *)uuid
91
+ resolve:(RCTPromiseResolveBlock)resolve
92
+ reject:(RCTPromiseRejectBlock)reject
93
+ {
52
94
  if (uuid != nil) {
53
- if (snapshotMap == nil) {
54
- snapshotMap = [[NSMutableDictionary alloc] init];
55
- }
56
- [snapshotMap removeObjectForKey:uuid];
95
+ [[RNSnapshotView getSnapShotMap] removeObjectForKey:uuid];
57
96
  }
58
97
  resolve(nil);
59
98
  }
60
99
 
61
- // Don't compile this code when we build for the old architecture.
62
- #ifdef RCT_NEW_ARCH_ENABLED
100
+ - (UIView *)viewForReactTag:(double)viewTag
101
+ {
102
+ RCTUIManager* uiManager = self.bridge.uiManager;
103
+ if (uiManager == nil) {
104
+ return nil;
105
+ }
106
+ return [uiManager viewForReactTag:[NSNumber numberWithDouble:viewTag]];
107
+ }
108
+
63
109
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
64
110
  (const facebook::react::ObjCTurboModule::InitParams &)params
65
111
  {
66
- return std::make_shared<facebook::react::NativeRNSnapshotViewSpecJSI>(params);
112
+ return std::make_shared<facebook::react::NativeRNSnapshotViewSpecJSI>(params);
67
113
  }
68
- #endif
69
-
70
114
 
71
115
  @end
@@ -1 +1 @@
1
- {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeRNSnapshotView.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AAOlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,gBAAgB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeRNSnapshotView.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AASlD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,gBAAgB,CAAC","ignoreList":[]}
@@ -0,0 +1,7 @@
1
+ import { codegenNativeComponent, type ViewProps } from 'react-native';
2
+
3
+ interface NativeProps extends ViewProps {
4
+ snapshotID?: string | null;
5
+ }
6
+
7
+ export default codegenNativeComponent<NativeProps>('RNSnapshotRenderer');
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
 
3
- import { forwardRef, useEffect, useRef } from 'react';
3
+ import { useEffect, useRef } from 'react';
4
4
  import RNSnapshotRenderer from './RNSnapshotRendererNativeComponent';
5
- import { releaseSnapshot } from '.';
5
+ import { releaseSnapshot } from "./index.js";
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
7
  /**
8
8
  * A view that renders a snapshot of a view.
@@ -11,7 +11,7 @@ const SnapshotRenderer = ({
11
11
  snapshotID,
12
12
  autoReleaseSnapshot = true,
13
13
  ...props
14
- }, forwardedRef) => {
14
+ }) => {
15
15
  const autoReleaseSnapshotRef = useRef(autoReleaseSnapshot);
16
16
  useEffect(() => {
17
17
  autoReleaseSnapshotRef.current = autoReleaseSnapshot;
@@ -22,10 +22,9 @@ const SnapshotRenderer = ({
22
22
  }
23
23
  }, [snapshotID]);
24
24
  return /*#__PURE__*/_jsx(RNSnapshotRenderer, {
25
- ref: forwardedRef,
26
25
  snapshotID: snapshotID,
27
26
  ...props
28
27
  });
29
28
  };
30
- export default /*#__PURE__*/forwardRef(SnapshotRenderer);
29
+ export default SnapshotRenderer;
31
30
  //# sourceMappingURL=SnapshotRenderer.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["forwardRef","useEffect","useRef","RNSnapshotRenderer","releaseSnapshot","jsx","_jsx","SnapshotRenderer","snapshotID","autoReleaseSnapshot","props","forwardedRef","autoReleaseSnapshotRef","current","catch","ref"],"sourceRoot":"../../src","sources":["SnapshotRenderer.tsx"],"mappings":";;AAAA,SAASA,UAAU,EAAEC,SAAS,EAAEC,MAAM,QAA2B,OAAO;AAExE,OAAOC,kBAAkB,MAAM,qCAAqC;AACpE,SAASC,eAAe,QAAQ,GAAG;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAepC;AACA;AACA;AACA,MAAMC,gBAAgB,GAAGA,CACvB;EAAEC,UAAU;EAAEC,mBAAmB,GAAG,IAAI;EAAE,GAAGC;AAA6B,CAAC,EAC3EC,YAAgC,KAC7B;EACH,MAAMC,sBAAsB,GAAGV,MAAM,CAACO,mBAAmB,CAAC;EAC1DR,SAAS,CAAC,MAAM;IACdW,sBAAsB,CAACC,OAAO,GAAGJ,mBAAmB;EACtD,CAAC,EAAE,CAACA,mBAAmB,CAAC,CAAC;EAEzBR,SAAS,CACP,MAAM,MAAM;IACV,IAAIW,sBAAsB,CAACC,OAAO,IAAIL,UAAU,EAAE;MAChDJ,eAAe,CAACI,UAAU,CAAC,CAACM,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C;EACF,CAAC,EACD,CAACN,UAAU,CACb,CAAC;EACD,oBACEF,IAAA,CAACH,kBAAkB;IAACY,GAAG,EAAEJ,YAAa;IAACH,UAAU,EAAEA,UAAW;IAAA,GAAKE;EAAK,CAAG,CAAC;AAEhF,CAAC;AAED,4BAAeV,UAAU,CAACO,gBAAgB,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["useEffect","useRef","RNSnapshotRenderer","releaseSnapshot","jsx","_jsx","SnapshotRenderer","snapshotID","autoReleaseSnapshot","props","autoReleaseSnapshotRef","current","catch"],"sourceRoot":"../../src","sources":["SnapshotRenderer.tsx"],"mappings":";;AAAA,SAASA,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAEzC,OAAOC,kBAAkB,MAAM,qCAAqC;AACpE,SAASC,eAAe,QAAQ,YAAG;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAepC;AACA;AACA;AACA,MAAMC,gBAAgB,GAAGA,CAAC;EACxBC,UAAU;EACVC,mBAAmB,GAAG,IAAI;EAC1B,GAAGC;AACkB,CAAC,KAAK;EAC3B,MAAMC,sBAAsB,GAAGT,MAAM,CAACO,mBAAmB,CAAC;EAC1DR,SAAS,CAAC,MAAM;IACdU,sBAAsB,CAACC,OAAO,GAAGH,mBAAmB;EACtD,CAAC,EAAE,CAACA,mBAAmB,CAAC,CAAC;EAEzBR,SAAS,CACP,MAAM,MAAM;IACV,IAAIU,sBAAsB,CAACC,OAAO,IAAIJ,UAAU,EAAE;MAChDJ,eAAe,CAACI,UAAU,CAAC,CAACK,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7C;EACF,CAAC,EACD,CAACL,UAAU,CACb,CAAC;EACD,oBAAOF,IAAA,CAACH,kBAAkB;IAACK,UAAU,EAAEA,UAAW;IAAA,GAAKE;EAAK,CAAG,CAAC;AAClE,CAAC;AAED,eAAeH,gBAAgB","ignoreList":[]}
@@ -1,19 +1,7 @@
1
1
  "use strict";
2
2
 
3
- import { findNodeHandle, NativeModules, Platform } from 'react-native';
4
- const LINKING_ERROR = `The package '@azzapp/react-native-snapshot-view' doesn't seem to be linked. Make sure: \n\n` + Platform.select({
5
- ios: "- You have run 'pod install'\n",
6
- default: ''
7
- }) + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
8
-
9
- // @ts-expect-error
10
- const isTurboModuleEnabled = global.__turboModuleProxy != null;
11
- const RNSnapshotViewModule = isTurboModuleEnabled ? require('./NativeRNSnapshotView').default : NativeModules.RNSnapshotView;
12
- const RNSnapshotView = RNSnapshotViewModule ? RNSnapshotViewModule : new Proxy({}, {
13
- get() {
14
- throw new Error(LINKING_ERROR);
15
- }
16
- });
3
+ import { findNodeHandle } from 'react-native';
4
+ import RNSnapshotView from "./NativeRNSnapshotView.js";
17
5
 
18
6
  /**
19
7
  * Captures a snapshot of a view. The snapshot can be rendered using the `SnapshotRenderer` component.
@@ -29,6 +17,25 @@ export function captureSnapshot(componentOrHandle) {
29
17
  return RNSnapshotView.captureSnapshot(handle);
30
18
  }
31
19
 
20
+ /**
21
+ * Captures a snapshot of the entire screen.
22
+ *
23
+ * @returns A promise that resolves to the ID of the snapshot. The snapshot should be released when no longer needed.
24
+ */
25
+ export function snapshotScreen() {
26
+ return RNSnapshotView.snapshotScreen();
27
+ }
28
+
29
+ /**
30
+ * Duplicates a snapshot. The duplicate is independent and must be released separately.
31
+ *
32
+ * @param snapshotID The ID of the snapshot to duplicate.
33
+ * @returns A promise that resolves to the ID of the duplicated snapshot.
34
+ */
35
+ export function duplicateSnapshot(snapshotID) {
36
+ return RNSnapshotView.duplicateSnapshot(snapshotID);
37
+ }
38
+
32
39
  /**
33
40
  * Releases a snapshot.
34
41
  *
@@ -38,5 +45,5 @@ export function captureSnapshot(componentOrHandle) {
38
45
  export function releaseSnapshot(snapshotID) {
39
46
  return RNSnapshotView.releaseSnapshot(snapshotID);
40
47
  }
41
- export { default as SnapshotRenderer } from './SnapshotRenderer';
48
+ export { default as SnapshotRenderer } from "./SnapshotRenderer.js";
42
49
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["findNodeHandle","NativeModules","Platform","LINKING_ERROR","select","ios","default","isTurboModuleEnabled","global","__turboModuleProxy","RNSnapshotViewModule","require","RNSnapshotView","Proxy","get","Error","captureSnapshot","componentOrHandle","handle","Promise","reject","releaseSnapshot","snapshotID","SnapshotRenderer"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,cAAc,EAAEC,aAAa,EAAEC,QAAQ,QAAQ,cAAc;AAEtE,MAAMC,aAAa,GACjB,6FAA6F,GAC7FD,QAAQ,CAACE,MAAM,CAAC;EAAEC,GAAG,EAAE,gCAAgC;EAAEC,OAAO,EAAE;AAAG,CAAC,CAAC,GACvE,sDAAsD,GACtD,+BAA+B;;AAEjC;AACA,MAAMC,oBAAoB,GAAGC,MAAM,CAACC,kBAAkB,IAAI,IAAI;AAE9D,MAAMC,oBAAoB,GAAGH,oBAAoB,GAC7CI,OAAO,CAAC,wBAAwB,CAAC,CAACL,OAAO,GACzCL,aAAa,CAACW,cAAc;AAEhC,MAAMA,cAAc,GAAGF,oBAAoB,GACvCA,oBAAoB,GACpB,IAAIG,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACZ,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASa,eAAeA,CAC7BC,iBAI6B,EACZ;EACjB,MAAMC,MAAM,GAAGlB,cAAc,CAACiB,iBAAiB,CAAC;EAChD,IAAIC,MAAM,IAAI,IAAI,EAAE;IAClB,OAAOC,OAAO,CAACC,MAAM,CAAC,IAAIL,KAAK,CAAC,qBAAqB,CAAC,CAAC;EACzD;EACA,OAAOH,cAAc,CAACI,eAAe,CAACE,MAAM,CAAC;AAC/C;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASG,eAAeA,CAACC,UAAkB,EAAiB;EACjE,OAAOV,cAAc,CAACS,eAAe,CAACC,UAAU,CAAC;AACnD;AAEA,SAAShB,OAAO,IAAIiB,gBAAgB,QAAQ,oBAAoB","ignoreList":[]}
1
+ {"version":3,"names":["findNodeHandle","RNSnapshotView","captureSnapshot","componentOrHandle","handle","Promise","reject","Error","snapshotScreen","duplicateSnapshot","snapshotID","releaseSnapshot","default","SnapshotRenderer"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,cAAc,QAAQ,cAAc;AAC7C,OAAOC,cAAc,MAAM,2BAAwB;;AAEnD;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAC7BC,iBAI6B,EACZ;EACjB,MAAMC,MAAM,GAAGJ,cAAc,CAACG,iBAAiB,CAAC;EAChD,IAAIC,MAAM,IAAI,IAAI,EAAE;IAClB,OAAOC,OAAO,CAACC,MAAM,CAAC,IAAIC,KAAK,CAAC,qBAAqB,CAAC,CAAC;EACzD;EACA,OAAON,cAAc,CAACC,eAAe,CAACE,MAAM,CAAC;AAC/C;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASI,cAAcA,CAAA,EAAoB;EAChD,OAAOP,cAAc,CAACO,cAAc,CAAC,CAAC;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,iBAAiBA,CAACC,UAAkB,EAAmB;EACrE,OAAOT,cAAc,CAACQ,iBAAiB,CAACC,UAAU,CAAC;AACrD;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,eAAeA,CAACD,UAAkB,EAAiB;EACjE,OAAOT,cAAc,CAACU,eAAe,CAACD,UAAU,CAAC;AACnD;AAEA,SAASE,OAAO,IAAIC,gBAAgB,QAAQ,uBAAoB","ignoreList":[]}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -1,6 +1,8 @@
1
1
  import type { TurboModule } from 'react-native';
2
2
  export interface Spec extends TurboModule {
3
3
  captureSnapshot(target: number): Promise<string>;
4
+ snapshotScreen(): Promise<string>;
5
+ duplicateSnapshot(snapshotID: string): Promise<string>;
4
6
  releaseSnapshot(a: string): Promise<void>;
5
7
  }
6
8
  declare const _default: Spec;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeRNSnapshotView.d.ts","sourceRoot":"","sources":["../../../src/NativeRNSnapshotView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;;AAED,wBAAwE"}
1
+ {"version":3,"file":"NativeRNSnapshotView.d.ts","sourceRoot":"","sources":["../../../src/NativeRNSnapshotView.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGhD,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAClC,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvD,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C;;AAED,wBAAwE"}
@@ -1,7 +1,7 @@
1
- import type { ViewProps } from 'react-native';
1
+ import { type ViewProps } from 'react-native';
2
2
  interface NativeProps extends ViewProps {
3
3
  snapshotID?: string | null;
4
4
  }
5
- declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
5
+ declare const _default: import("react-native/types_generated/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
6
6
  export default _default;
7
7
  //# sourceMappingURL=RNSnapshotRendererNativeComponent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"RNSnapshotRendererNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/RNSnapshotRendererNativeComponent.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,UAAU,WAAY,SAAQ,SAAS;IACrC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;;AAED,wBAAyE"}
1
+ {"version":3,"file":"RNSnapshotRendererNativeComponent.d.ts","sourceRoot":"","sources":["../../../src/RNSnapshotRendererNativeComponent.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAEtE,UAAU,WAAY,SAAQ,SAAS;IACrC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;;AAED,wBAAyE"}
@@ -1,4 +1,4 @@
1
- import type { View, ViewProps } from 'react-native';
1
+ import type { ViewProps } from 'react-native';
2
2
  export type SnapshotRendererProps = Omit<ViewProps, 'children'> & {
3
3
  /**
4
4
  * The ID of the snapshot to render.
@@ -11,17 +11,9 @@ export type SnapshotRendererProps = Omit<ViewProps, 'children'> & {
11
11
  */
12
12
  autoReleaseSnapshot?: boolean;
13
13
  };
14
- declare const _default: import("react").ForwardRefExoticComponent<Omit<ViewProps, "children"> & {
15
- /**
16
- * The ID of the snapshot to render.
17
- * This ID is returned by the `captureSnapshot` function.
18
- */
19
- snapshotID: string | null;
20
- /**
21
- * Whether to automatically release the snapshot when no longer displayed.
22
- * @default true
23
- */
24
- autoReleaseSnapshot?: boolean;
25
- } & import("react").RefAttributes<View>>;
26
- export default _default;
14
+ /**
15
+ * A view that renders a snapshot of a view.
16
+ */
17
+ declare const SnapshotRenderer: ({ snapshotID, autoReleaseSnapshot, ...props }: SnapshotRendererProps) => import("react/jsx-runtime").JSX.Element;
18
+ export default SnapshotRenderer;
27
19
  //# sourceMappingURL=SnapshotRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SnapshotRenderer.d.ts","sourceRoot":"","sources":["../../../src/SnapshotRenderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAIpD,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG;IAChE;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;;IAVA;;;OAGG;gBACS,MAAM,GAAG,IAAI;IACzB;;;OAGG;0BACmB,OAAO;;AA4B/B,wBAA4C"}
1
+ {"version":3,"file":"SnapshotRenderer.d.ts","sourceRoot":"","sources":["../../../src/SnapshotRenderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG;IAChE;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF;;GAEG;AACH,QAAA,MAAM,gBAAgB,GAAI,+CAIvB,qBAAqB,4CAevB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
@@ -5,6 +5,19 @@
5
5
  * @returns A promise that resolves to the ID of the snapshot. The snapshot should be released when no longer needed.
6
6
  */
7
7
  export declare function captureSnapshot(componentOrHandle: null | number | React.Component<any, any> | React.ComponentClass<any>): Promise<string>;
8
+ /**
9
+ * Captures a snapshot of the entire screen.
10
+ *
11
+ * @returns A promise that resolves to the ID of the snapshot. The snapshot should be released when no longer needed.
12
+ */
13
+ export declare function snapshotScreen(): Promise<string>;
14
+ /**
15
+ * Duplicates a snapshot. The duplicate is independent and must be released separately.
16
+ *
17
+ * @param snapshotID The ID of the snapshot to duplicate.
18
+ * @returns A promise that resolves to the ID of the duplicated snapshot.
19
+ */
20
+ export declare function duplicateSnapshot(snapshotID: string): Promise<string>;
8
21
  /**
9
22
  * Releases a snapshot.
10
23
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AA0BA;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,iBAAiB,EACb,IAAI,GACJ,MAAM,GACN,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,GACzB,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjE;AAED,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,iBAAiB,EACb,IAAI,GACJ,MAAM,GACN,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,GACzB,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAEhD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAErE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjE;AAED,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@azzapp/react-native-snapshot-view",
3
- "version": "0.1.4",
3
+ "version": "0.3.0",
4
4
  "description": "Snapshot view for react-native",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -14,6 +14,7 @@
14
14
  "ios",
15
15
  "cpp",
16
16
  "*.podspec",
17
+ "react-native.config.js",
17
18
  "!ios/build",
18
19
  "!android/build",
19
20
  "!android/gradle",
@@ -26,13 +27,13 @@
26
27
  "!**/.*"
27
28
  ],
28
29
  "scripts": {
29
- "example": "yarn workspace @azzapp/react-native-snapshot-view-example",
30
+ "example": "yarn workspace react-native-snapshot-view-example",
30
31
  "test": "jest",
31
32
  "typecheck": "tsc",
32
33
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
33
34
  "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
34
35
  "prepare": "bob build",
35
- "release": "release-it"
36
+ "release": "release-it --only-version"
36
37
  },
37
38
  "keywords": [
38
39
  "react-native",
@@ -54,29 +55,30 @@
54
55
  "access": "public"
55
56
  },
56
57
  "devDependencies": {
57
- "@commitlint/config-conventional": "^17.0.2",
58
- "@evilmartians/lefthook": "^1.5.0",
59
- "@react-native/eslint-config": "^0.73.1",
60
- "@release-it/conventional-changelog": "^5.0.0",
61
- "@types/jest": "^29.5.5",
62
- "@types/react": "^18.2.44",
63
- "commitlint": "^17.0.2",
64
- "del-cli": "^5.1.0",
65
- "eslint": "^8.51.0",
66
- "eslint-config-prettier": "^9.0.0",
67
- "eslint-plugin-prettier": "^5.0.1",
58
+ "@commitlint/config-conventional": "^19.8.1",
59
+ "@eslint/compat": "^1.3.2",
60
+ "@eslint/eslintrc": "^3.3.1",
61
+ "@eslint/js": "^9.35.0",
62
+ "@evilmartians/lefthook": "^1.12.3",
63
+ "@react-native-community/cli": "20.0.1",
64
+ "@react-native/babel-preset": "0.81.1",
65
+ "@react-native/eslint-config": "^0.81.1",
66
+ "@release-it/conventional-changelog": "^10.0.1",
67
+ "@types/jest": "^29.5.14",
68
+ "@types/react": "^19.1.0",
69
+ "commitlint": "^19.8.1",
70
+ "del-cli": "^6.0.0",
71
+ "eslint": "^9.35.0",
72
+ "eslint-config-prettier": "^10.1.8",
73
+ "eslint-plugin-prettier": "^5.5.4",
68
74
  "jest": "^29.7.0",
69
- "prettier": "^3.0.3",
70
- "react": "18.3.1",
71
- "react-native": "0.75.3",
72
- "react-native-builder-bob": "^0.30.2",
73
- "release-it": "^15.0.0",
74
- "turbo": "^1.10.7",
75
- "typescript": "^5.2.2"
76
- },
77
- "resolutions": {
78
- "@types/react": "^18.2.44",
79
- "react-native-builder-bob@^0.30.2": "patch:react-native-builder-bob@npm%3A0.30.2#./.yarn/patches/react-native-builder-bob-npm-0.30.2-5e6e62dece.patch"
75
+ "prettier": "^3.6.2",
76
+ "react": "19.1.0",
77
+ "react-native": "0.81.1",
78
+ "react-native-builder-bob": "^0.40.13",
79
+ "release-it": "^19.0.4",
80
+ "turbo": "^2.5.6",
81
+ "typescript": "^5.9.2"
80
82
  },
81
83
  "peerDependencies": {
82
84
  "react": "*",
@@ -115,30 +117,6 @@
115
117
  }
116
118
  }
117
119
  },
118
- "eslintConfig": {
119
- "root": true,
120
- "extends": [
121
- "@react-native",
122
- "prettier"
123
- ],
124
- "rules": {
125
- "react/react-in-jsx-scope": "off",
126
- "prettier/prettier": [
127
- "error",
128
- {
129
- "quoteProps": "consistent",
130
- "singleQuote": true,
131
- "tabWidth": 2,
132
- "trailingComma": "es5",
133
- "useTabs": false
134
- }
135
- ]
136
- }
137
- },
138
- "eslintIgnore": [
139
- "node_modules/",
140
- "lib/"
141
- ],
142
120
  "prettier": {
143
121
  "quoteProps": "consistent",
144
122
  "singleQuote": true,
@@ -150,8 +128,12 @@
150
128
  "source": "src",
151
129
  "output": "lib",
152
130
  "targets": [
153
- "commonjs",
154
- "module",
131
+ [
132
+ "module",
133
+ {
134
+ "esm": true
135
+ }
136
+ ],
155
137
  [
156
138
  "typescript",
157
139
  {
@@ -166,10 +148,16 @@
166
148
  "jsSrcsDir": "src",
167
149
  "android": {
168
150
  "javaPackageName": "com.azzapp.rnsnapshotview"
151
+ },
152
+ "ios": {
153
+ "componentProvider": {
154
+ "RNSnapshotRenderer": "RNSnapshotRenderer"
155
+ }
169
156
  }
170
157
  },
171
158
  "create-react-native-library": {
172
- "type": "view-mixed",
173
- "version": "0.41.2"
159
+ "languages": "kotlin-objc",
160
+ "type": "fabric-view",
161
+ "version": "0.54.3"
174
162
  }
175
163
  }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @type {import('@react-native-community/cli-types').UserDependencyConfig}
3
+ */
4
+ module.exports = {};
@@ -3,6 +3,8 @@ import { TurboModuleRegistry } from 'react-native';
3
3
 
4
4
  export interface Spec extends TurboModule {
5
5
  captureSnapshot(target: number): Promise<string>;
6
+ snapshotScreen(): Promise<string>;
7
+ duplicateSnapshot(snapshotID: string): Promise<string>;
6
8
  releaseSnapshot(a: string): Promise<void>;
7
9
  }
8
10
 
@@ -1,5 +1,4 @@
1
- import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
2
- import type { ViewProps } from 'react-native';
1
+ import { codegenNativeComponent, type ViewProps } from 'react-native';
3
2
 
4
3
  interface NativeProps extends ViewProps {
5
4
  snapshotID?: string | null;
@@ -1,5 +1,5 @@
1
- import { forwardRef, useEffect, useRef, type ForwardedRef } from 'react';
2
- import type { View, ViewProps } from 'react-native';
1
+ import { useEffect, useRef } from 'react';
2
+ import type { ViewProps } from 'react-native';
3
3
  import RNSnapshotRenderer from './RNSnapshotRendererNativeComponent';
4
4
  import { releaseSnapshot } from '.';
5
5
 
@@ -19,10 +19,11 @@ export type SnapshotRendererProps = Omit<ViewProps, 'children'> & {
19
19
  /**
20
20
  * A view that renders a snapshot of a view.
21
21
  */
22
- const SnapshotRenderer = (
23
- { snapshotID, autoReleaseSnapshot = true, ...props }: SnapshotRendererProps,
24
- forwardedRef: ForwardedRef<View>
25
- ) => {
22
+ const SnapshotRenderer = ({
23
+ snapshotID,
24
+ autoReleaseSnapshot = true,
25
+ ...props
26
+ }: SnapshotRendererProps) => {
26
27
  const autoReleaseSnapshotRef = useRef(autoReleaseSnapshot);
27
28
  useEffect(() => {
28
29
  autoReleaseSnapshotRef.current = autoReleaseSnapshot;
@@ -36,9 +37,7 @@ const SnapshotRenderer = (
36
37
  },
37
38
  [snapshotID]
38
39
  );
39
- return (
40
- <RNSnapshotRenderer ref={forwardedRef} snapshotID={snapshotID} {...props} />
41
- );
40
+ return <RNSnapshotRenderer snapshotID={snapshotID} {...props} />;
42
41
  };
43
42
 
44
- export default forwardRef(SnapshotRenderer);
43
+ export default SnapshotRenderer;
package/src/index.tsx CHANGED
@@ -1,28 +1,5 @@
1
- import { findNodeHandle, NativeModules, Platform } from 'react-native';
2
-
3
- const LINKING_ERROR =
4
- `The package '@azzapp/react-native-snapshot-view' doesn't seem to be linked. Make sure: \n\n` +
5
- Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6
- '- You rebuilt the app after installing the package\n' +
7
- '- You are not using Expo Go\n';
8
-
9
- // @ts-expect-error
10
- const isTurboModuleEnabled = global.__turboModuleProxy != null;
11
-
12
- const RNSnapshotViewModule = isTurboModuleEnabled
13
- ? require('./NativeRNSnapshotView').default
14
- : NativeModules.RNSnapshotView;
15
-
16
- const RNSnapshotView = RNSnapshotViewModule
17
- ? RNSnapshotViewModule
18
- : new Proxy(
19
- {},
20
- {
21
- get() {
22
- throw new Error(LINKING_ERROR);
23
- },
24
- }
25
- );
1
+ import { findNodeHandle } from 'react-native';
2
+ import RNSnapshotView from './NativeRNSnapshotView';
26
3
 
27
4
  /**
28
5
  * Captures a snapshot of a view. The snapshot can be rendered using the `SnapshotRenderer` component.
@@ -44,6 +21,25 @@ export function captureSnapshot(
44
21
  return RNSnapshotView.captureSnapshot(handle);
45
22
  }
46
23
 
24
+ /**
25
+ * Captures a snapshot of the entire screen.
26
+ *
27
+ * @returns A promise that resolves to the ID of the snapshot. The snapshot should be released when no longer needed.
28
+ */
29
+ export function snapshotScreen(): Promise<string> {
30
+ return RNSnapshotView.snapshotScreen();
31
+ }
32
+
33
+ /**
34
+ * Duplicates a snapshot. The duplicate is independent and must be released separately.
35
+ *
36
+ * @param snapshotID The ID of the snapshot to duplicate.
37
+ * @returns A promise that resolves to the ID of the duplicated snapshot.
38
+ */
39
+ export function duplicateSnapshot(snapshotID: string): Promise<string> {
40
+ return RNSnapshotView.duplicateSnapshot(snapshotID);
41
+ }
42
+
47
43
  /**
48
44
  * Releases a snapshot.
49
45
  *
@@ -1,2 +0,0 @@
1
- <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
- </manifest>
@@ -1,21 +0,0 @@
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
- }
@@ -1,7 +0,0 @@
1
- package com.azzapp.rnsnapshotview
2
-
3
- import com.facebook.react.bridge.ReactApplicationContext
4
-
5
- abstract class RNSnapshotViewSpec internal constructor(context: ReactApplicationContext) :
6
- NativeRNSnapshotViewSpec(context) {
7
- }
@@ -1,9 +0,0 @@
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
- }
@@ -1,12 +0,0 @@
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
- }
@@ -1,62 +0,0 @@
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
@@ -1,5 +0,0 @@
1
- "use strict";
2
-
3
- import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
4
- export default codegenNativeComponent('RNSnapshotRenderer');
5
- //# sourceMappingURL=RNSnapshotRendererNativeComponent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["codegenNativeComponent"],"sourceRoot":"../../src","sources":["RNSnapshotRendererNativeComponent.ts"],"mappings":";;AAAA,OAAOA,sBAAsB,MAAM,yDAAyD;AAO5F,eAAeA,sBAAsB,CAAc,oBAAoB,CAAC","ignoreList":[]}