react-native-inapp-inspector 2.5.12 → 2.5.14

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 (392) hide show
  1. package/README.md +0 -8
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  4. package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
  5. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  6. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  7. package/android/.gradle/8.9/gc.properties +0 -0
  8. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  9. package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
  10. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  11. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  12. package/android/.gradle/9.2.0/gc.properties +0 -0
  13. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  14. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  15. package/android/.gradle/vcs-1/gc.properties +0 -0
  16. package/android/.settings/org.eclipse.buildship.core.prefs +13 -0
  17. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/results.bin +1 -0
  18. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/BuildConfig.dex +0 -0
  19. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/InAppInspectorFloatingView$iconView$1.dex +0 -0
  20. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/InAppInspectorFloatingView.dex +0 -0
  21. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NativeNetworkInspectorSpec.dex +0 -0
  22. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$Companion.dex +0 -0
  23. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$activityEventListener$1.dex +0 -0
  24. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$frameCallback$1.dex +0 -0
  25. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$getCapturedMedia$lambda$62$$inlined$sortedByDescending$1.dex +0 -0
  26. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$shakeListener$1.dex +0 -0
  27. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule$startVideoRecording$2$1.dex +0 -0
  28. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorModule.dex +0 -0
  29. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/bundleLibRuntimeToDirDebug_dex/com/inappinspector/NetworkInspectorPackage.dex +0 -0
  30. package/android/build/.transforms/ad628164ecef2a7cc593f0fd2f4050ce/transformed/bundleLibRuntimeToDirDebug/desugar_graph.bin +0 -0
  31. package/android/build/.transforms/c93e459e24d856bde563ebb048265732/results.bin +1 -0
  32. package/android/build/.transforms/c93e459e24d856bde563ebb048265732/transformed/classes/classes_dex/classes.dex +0 -0
  33. package/android/build/generated/source/buildConfig/debug/com/inappinspector/BuildConfig.java +10 -0
  34. package/android/build/generated/source/codegen/java/com/inappinspector/NativeNetworkInspectorSpec.java +176 -0
  35. package/android/build/generated/source/codegen/jni/CMakeLists.txt +28 -0
  36. package/android/build/generated/source/codegen/jni/RNInAppInspectorSpec-generated.cpp +236 -0
  37. package/android/build/generated/source/codegen/jni/RNInAppInspectorSpec.h +31 -0
  38. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ComponentDescriptors.cpp +22 -0
  39. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ComponentDescriptors.h +24 -0
  40. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/EventEmitters.cpp +16 -0
  41. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/EventEmitters.h +17 -0
  42. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/Props.cpp +19 -0
  43. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/Props.h +18 -0
  44. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/RNInAppInspectorSpecJSI.h +337 -0
  45. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ShadowNodes.cpp +17 -0
  46. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/ShadowNodes.h +23 -0
  47. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/States.cpp +16 -0
  48. package/android/build/generated/source/codegen/jni/react/renderer/components/RNInAppInspectorSpec/States.h +20 -0
  49. package/android/build/generated/source/codegen/schema.json +1 -0
  50. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/AndroidManifest.xml +19 -0
  51. package/android/build/intermediates/aapt_friendly_merged_manifests/debug/processDebugManifest/aapt/output-metadata.json +18 -0
  52. package/android/build/intermediates/aar_metadata/debug/writeDebugAarMetadata/aar-metadata.properties +6 -0
  53. package/android/build/intermediates/annotation_processor_list/debug/javaPreCompileDebug/annotationProcessors.json +1 -0
  54. package/android/build/intermediates/compile_library_classes_jar/debug/bundleLibCompileToJarDebug/classes.jar +0 -0
  55. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  56. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +1 -0
  57. package/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/xml_inappinspector_file_paths.xml.flat +0 -0
  58. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +2 -0
  59. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +2 -0
  60. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +2 -0
  61. package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +2 -0
  62. package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +2 -0
  63. package/android/build/intermediates/java_res/debug/processDebugJavaRes/out/META-INF/react-native-inapp-inspector_debug.kotlin_module +0 -0
  64. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/inappinspector/BuildConfig.class +0 -0
  65. package/android/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/com/inappinspector/NativeNetworkInspectorSpec.class +0 -0
  66. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +3 -0
  67. package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +28 -0
  68. package/android/build/intermediates/merged_manifest/debug/processDebugManifest/AndroidManifest.xml +19 -0
  69. package/android/build/intermediates/navigation_json/debug/extractDeepLinksDebug/navigation.json +1 -0
  70. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +1 -0
  71. package/android/build/intermediates/packaged_res/debug/packageDebugResources/xml/inappinspector_file_paths.xml +7 -0
  72. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/META-INF/react-native-inapp-inspector_debug.kotlin_module +0 -0
  73. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/BuildConfig.class +0 -0
  74. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/InAppInspectorFloatingView$iconView$1.class +0 -0
  75. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/InAppInspectorFloatingView.class +0 -0
  76. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NativeNetworkInspectorSpec.class +0 -0
  77. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$Companion.class +0 -0
  78. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$activityEventListener$1.class +0 -0
  79. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$frameCallback$1.class +0 -0
  80. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$getCapturedMedia$lambda$62$$inlined$sortedByDescending$1.class +0 -0
  81. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$shakeListener$1.class +0 -0
  82. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule$startVideoRecording$2$1.class +0 -0
  83. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorModule.class +0 -0
  84. package/android/build/intermediates/runtime_library_classes_dir/debug/bundleLibRuntimeToDirDebug/com/inappinspector/NetworkInspectorPackage.class +0 -0
  85. package/android/build/intermediates/runtime_library_classes_jar/debug/bundleLibRuntimeToJarDebug/classes.jar +0 -0
  86. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +2 -0
  87. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab +0 -0
  88. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream +0 -0
  89. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.keystream.len +0 -0
  90. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.len +0 -0
  91. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab.values.at +0 -0
  92. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i +0 -0
  93. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/inputs/source-to-output.tab_i.len +0 -0
  94. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab +0 -0
  95. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream +0 -0
  96. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.keystream.len +0 -0
  97. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.len +0 -0
  98. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab.values.at +0 -0
  99. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i +0 -0
  100. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-attributes.tab_i.len +0 -0
  101. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab +0 -0
  102. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream +0 -0
  103. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.keystream.len +0 -0
  104. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.len +0 -0
  105. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab.values.at +0 -0
  106. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i +0 -0
  107. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/class-fq-name-to-source.tab_i.len +0 -0
  108. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab +0 -0
  109. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream +0 -0
  110. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.keystream.len +0 -0
  111. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.len +0 -0
  112. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab.values.at +0 -0
  113. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i +0 -0
  114. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/constants.tab_i.len +0 -0
  115. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab +0 -0
  116. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream +0 -0
  117. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.keystream.len +0 -0
  118. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.len +0 -0
  119. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab.values.at +0 -0
  120. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i +0 -0
  121. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/internal-name-to-source.tab_i.len +0 -0
  122. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab +0 -0
  123. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream +0 -0
  124. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.keystream.len +0 -0
  125. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.len +0 -0
  126. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab.values.at +0 -0
  127. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i +0 -0
  128. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/proto.tab_i.len +0 -0
  129. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab +0 -0
  130. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream +0 -0
  131. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.keystream.len +0 -0
  132. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.len +0 -0
  133. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab.values.at +0 -0
  134. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i +0 -0
  135. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/source-to-classes.tab_i.len +0 -0
  136. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab +0 -0
  137. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream +0 -0
  138. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.keystream.len +0 -0
  139. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.len +0 -0
  140. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab.values.at +0 -0
  141. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i +0 -0
  142. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/subtypes.tab_i.len +0 -0
  143. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab +0 -0
  144. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream +0 -0
  145. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.keystream.len +0 -0
  146. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.len +0 -0
  147. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab.values.at +0 -0
  148. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i +0 -0
  149. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/jvm/kotlin/supertypes.tab_i.len +0 -0
  150. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/counters.tab +2 -0
  151. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab +0 -0
  152. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream +0 -0
  153. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.keystream.len +0 -0
  154. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.len +0 -0
  155. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab.values.at +0 -0
  156. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i +0 -0
  157. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/file-to-id.tab_i.len +0 -0
  158. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab +0 -0
  159. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream +0 -0
  160. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.keystream.len +0 -0
  161. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.len +0 -0
  162. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab.values.at +0 -0
  163. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i +0 -0
  164. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/id-to-file.tab_i.len +0 -0
  165. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab +0 -0
  166. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream +0 -0
  167. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.keystream.len +0 -0
  168. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.len +0 -0
  169. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab.values.at +0 -0
  170. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i +0 -0
  171. package/android/build/kotlin/compileDebugKotlin/cacheable/caches-jvm/lookups/lookups.tab_i.len +0 -0
  172. package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
  173. package/android/build/kotlin/compileDebugKotlin/classpath-snapshot/shrunk-classpath-snapshot.bin +0 -0
  174. package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
  175. package/android/build/outputs/logs/manifest-merger-debug-report.txt +35 -0
  176. package/android/build/tmp/compileDebugJavaWithJavac/previous-compilation-data.bin +0 -0
  177. package/android/build/tmp/kotlin-classes/debug/META-INF/react-native-inapp-inspector_debug.kotlin_module +0 -0
  178. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/InAppInspectorFloatingView$iconView$1.class +0 -0
  179. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/InAppInspectorFloatingView.class +0 -0
  180. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$Companion.class +0 -0
  181. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$activityEventListener$1.class +0 -0
  182. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$frameCallback$1.class +0 -0
  183. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$getCapturedMedia$lambda$62$$inlined$sortedByDescending$1.class +0 -0
  184. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$shakeListener$1.class +0 -0
  185. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule$startVideoRecording$2$1.class +0 -0
  186. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorModule.class +0 -0
  187. package/android/build/tmp/kotlin-classes/debug/com/inappinspector/NetworkInspectorPackage.class +0 -0
  188. package/android/src/main/AndroidManifest.xml +11 -0
  189. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +492 -45
  190. package/android/src/main/res/xml/inappinspector_file_paths.xml +7 -0
  191. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +47 -49
  192. package/dist/commonjs/components/Inspector/BoxModelVisualizer.d.ts +8 -0
  193. package/dist/commonjs/components/Inspector/BoxModelVisualizer.js +76 -0
  194. package/dist/commonjs/components/Inspector/ConsoleExportModal.js +51 -51
  195. package/dist/commonjs/components/Inspector/ConsoleTab.js +7 -7
  196. package/dist/commonjs/components/Inspector/CrashTab.js +17 -17
  197. package/dist/commonjs/components/Inspector/DebuggingTab.js +37 -37
  198. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +2 -2
  199. package/dist/commonjs/components/Inspector/FabLauncher.js +4 -4
  200. package/dist/commonjs/components/Inspector/FloatingCaptureWidget.js +2 -2
  201. package/dist/commonjs/components/Inspector/InspectorHeader.js +36 -36
  202. package/dist/commonjs/components/Inspector/MainScreen.js +38 -75
  203. package/dist/commonjs/components/Inspector/MediaGalleryTab.js +10 -10
  204. package/dist/commonjs/components/Inspector/MediaPreviewModal.d.ts +1 -0
  205. package/dist/commonjs/components/Inspector/MediaPreviewModal.js +222 -222
  206. package/dist/commonjs/components/Inspector/NetworkExportModal.d.ts +10 -0
  207. package/dist/commonjs/components/Inspector/NetworkExportModal.js +333 -0
  208. package/dist/commonjs/components/Inspector/NetworkTab.js +60 -53
  209. package/dist/commonjs/components/Inspector/NpmStarPrompt.js +11 -12
  210. package/dist/commonjs/components/Inspector/ReduxDetail.js +17 -19
  211. package/dist/commonjs/components/Inspector/ReduxTab.js +5 -5
  212. package/dist/commonjs/components/Inspector/SecondaryTelemetryStrip.d.ts +1 -0
  213. package/dist/commonjs/components/Inspector/SecondaryTelemetryStrip.js +17 -16
  214. package/dist/commonjs/components/Inspector/SettingsPanel.js +43 -47
  215. package/dist/commonjs/components/Inspector/SkeletonPlaceholder.d.ts +3 -0
  216. package/dist/commonjs/components/Inspector/SkeletonPlaceholder.js +34 -3
  217. package/dist/commonjs/components/Inspector/SocketCard.js +2 -2
  218. package/dist/commonjs/components/Inspector/SupportPage.js +5 -5
  219. package/dist/commonjs/components/Inspector/TabBar.js +9 -15
  220. package/dist/commonjs/components/Inspector/UiA11yAuditPanel.d.ts +7 -0
  221. package/dist/commonjs/components/Inspector/UiA11yAuditPanel.js +97 -0
  222. package/dist/commonjs/components/Inspector/UiInspectorDetail.d.ts +2 -0
  223. package/dist/commonjs/components/Inspector/UiInspectorDetail.js +485 -0
  224. package/dist/commonjs/components/Inspector/UiInspectorOverlay.d.ts +2 -0
  225. package/dist/commonjs/components/Inspector/UiInspectorOverlay.js +199 -0
  226. package/dist/commonjs/components/Inspector/UiInspectorTab.d.ts +2 -0
  227. package/dist/commonjs/components/Inspector/UiInspectorTab.js +117 -0
  228. package/dist/commonjs/components/Inspector/UiLiveStyleTweaker.d.ts +10 -0
  229. package/dist/commonjs/components/Inspector/UiLiveStyleTweaker.js +148 -0
  230. package/dist/commonjs/components/Inspector/index.d.ts +28 -0
  231. package/dist/commonjs/components/Inspector/index.js +1 -0
  232. package/dist/commonjs/components/LogCard.js +12 -10
  233. package/dist/commonjs/components/SkeletonPlaceholder.d.ts +3 -0
  234. package/dist/commonjs/components/SkeletonPlaceholder.js +34 -3
  235. package/dist/commonjs/constants/index.js +1 -1
  236. package/dist/commonjs/constants/telemetryConfig.d.ts +3 -3
  237. package/dist/commonjs/constants/telemetryConfig.js +1 -1
  238. package/dist/commonjs/constants/version.d.ts +1 -1
  239. package/dist/commonjs/constants/version.js +1 -1
  240. package/dist/commonjs/customHooks/crashHandler.d.ts +1 -1
  241. package/dist/commonjs/customHooks/crashHandler.js +6 -6
  242. package/dist/commonjs/customHooks/uiInspectorManager.d.ts +22 -0
  243. package/dist/commonjs/customHooks/uiInspectorManager.js +1 -0
  244. package/dist/commonjs/helpers/index.js +1 -3
  245. package/dist/commonjs/helpers/remoteConfig.js +1 -1
  246. package/dist/commonjs/helpers/searchQueryParser.d.ts +1 -0
  247. package/dist/commonjs/helpers/searchQueryParser.js +7 -5
  248. package/dist/commonjs/helpers/shareFormatter.d.ts +16 -0
  249. package/dist/commonjs/helpers/shareFormatter.js +16 -9
  250. package/dist/commonjs/helpers/uiInspectorEngine.d.ts +62 -0
  251. package/dist/commonjs/helpers/uiInspectorEngine.js +19 -0
  252. package/dist/commonjs/i18n/locales/ar.json +1 -1
  253. package/dist/commonjs/i18n/locales/bn.json +1 -1
  254. package/dist/commonjs/i18n/locales/de.json +1 -1
  255. package/dist/commonjs/i18n/locales/en.json +1 -1
  256. package/dist/commonjs/i18n/locales/es.json +1 -1
  257. package/dist/commonjs/i18n/locales/fr.json +1 -1
  258. package/dist/commonjs/i18n/locales/gu.json +1 -1
  259. package/dist/commonjs/i18n/locales/hi.json +1 -1
  260. package/dist/commonjs/i18n/locales/id.json +1 -1
  261. package/dist/commonjs/i18n/locales/it.json +1 -1
  262. package/dist/commonjs/i18n/locales/ja.json +1 -1
  263. package/dist/commonjs/i18n/locales/kn.json +1 -1
  264. package/dist/commonjs/i18n/locales/ko.json +1 -1
  265. package/dist/commonjs/i18n/locales/ml.json +1 -1
  266. package/dist/commonjs/i18n/locales/mr.json +1 -1
  267. package/dist/commonjs/i18n/locales/nl.json +1 -1
  268. package/dist/commonjs/i18n/locales/pa.json +1 -1
  269. package/dist/commonjs/i18n/locales/pl.json +1 -1
  270. package/dist/commonjs/i18n/locales/pt.json +1 -1
  271. package/dist/commonjs/i18n/locales/ru.json +1 -1
  272. package/dist/commonjs/i18n/locales/ta.json +1 -1
  273. package/dist/commonjs/i18n/locales/te.json +1 -1
  274. package/dist/commonjs/i18n/locales/tr.json +1 -1
  275. package/dist/commonjs/i18n/locales/vi.json +1 -1
  276. package/dist/commonjs/i18n/locales/zh.json +1 -1
  277. package/dist/commonjs/index.d.ts +4 -2
  278. package/dist/commonjs/index.js +3 -3
  279. package/dist/commonjs/native/NativeInspector.d.ts +4 -0
  280. package/dist/commonjs/native/NativeInspector.js +1 -1
  281. package/dist/commonjs/native/NativeNetworkInspector.d.ts +4 -0
  282. package/dist/commonjs/styles/AppFonts.d.ts +4 -0
  283. package/dist/commonjs/styles/AppFonts.js +1 -1
  284. package/dist/commonjs/styles/index.d.ts +2 -0
  285. package/dist/commonjs/styles/index.js +1 -1
  286. package/dist/commonjs/types/editor.d.ts +31 -0
  287. package/dist/commonjs/types/enums.d.ts +0 -2
  288. package/dist/commonjs/types/enums.js +1 -1
  289. package/dist/commonjs/types/interfaces.d.ts +1 -1
  290. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +73 -75
  291. package/dist/esm/components/Inspector/BoxModelVisualizer.d.ts +8 -0
  292. package/dist/esm/components/Inspector/BoxModelVisualizer.js +76 -0
  293. package/dist/esm/components/Inspector/ConsoleExportModal.js +67 -67
  294. package/dist/esm/components/Inspector/ConsoleTab.js +48 -48
  295. package/dist/esm/components/Inspector/CrashTab.js +58 -58
  296. package/dist/esm/components/Inspector/DebuggingTab.js +105 -105
  297. package/dist/esm/components/Inspector/DeviceInfoTab.js +2 -2
  298. package/dist/esm/components/Inspector/FabLauncher.js +50 -50
  299. package/dist/esm/components/Inspector/FloatingCaptureWidget.js +23 -23
  300. package/dist/esm/components/Inspector/InspectorHeader.js +64 -64
  301. package/dist/esm/components/Inspector/MainScreen.js +87 -124
  302. package/dist/esm/components/Inspector/MediaGalleryTab.js +151 -151
  303. package/dist/esm/components/Inspector/MediaPreviewModal.d.ts +1 -0
  304. package/dist/esm/components/Inspector/MediaPreviewModal.js +468 -468
  305. package/dist/esm/components/Inspector/NetworkExportModal.d.ts +10 -0
  306. package/dist/esm/components/Inspector/NetworkExportModal.js +333 -0
  307. package/dist/esm/components/Inspector/NetworkTab.js +143 -136
  308. package/dist/esm/components/Inspector/NpmStarPrompt.js +32 -33
  309. package/dist/esm/components/Inspector/ReduxDetail.js +54 -56
  310. package/dist/esm/components/Inspector/ReduxTab.js +9 -9
  311. package/dist/esm/components/Inspector/SecondaryTelemetryStrip.d.ts +1 -0
  312. package/dist/esm/components/Inspector/SecondaryTelemetryStrip.js +23 -22
  313. package/dist/esm/components/Inspector/SettingsPanel.js +109 -113
  314. package/dist/esm/components/Inspector/SkeletonPlaceholder.d.ts +3 -0
  315. package/dist/esm/components/Inspector/SkeletonPlaceholder.js +42 -11
  316. package/dist/esm/components/Inspector/SocketCard.js +13 -13
  317. package/dist/esm/components/Inspector/SupportPage.js +5 -5
  318. package/dist/esm/components/Inspector/TabBar.js +35 -41
  319. package/dist/esm/components/Inspector/UiA11yAuditPanel.d.ts +7 -0
  320. package/dist/esm/components/Inspector/UiA11yAuditPanel.js +97 -0
  321. package/dist/esm/components/Inspector/UiInspectorDetail.d.ts +2 -0
  322. package/dist/esm/components/Inspector/UiInspectorDetail.js +422 -0
  323. package/dist/esm/components/Inspector/UiInspectorOverlay.d.ts +2 -0
  324. package/dist/esm/components/Inspector/UiInspectorOverlay.js +138 -0
  325. package/dist/esm/components/Inspector/UiInspectorTab.d.ts +2 -0
  326. package/dist/esm/components/Inspector/UiInspectorTab.js +117 -0
  327. package/dist/esm/components/Inspector/UiLiveStyleTweaker.d.ts +10 -0
  328. package/dist/esm/components/Inspector/UiLiveStyleTweaker.js +148 -0
  329. package/dist/esm/components/Inspector/index.d.ts +28 -0
  330. package/dist/esm/components/Inspector/index.js +1 -0
  331. package/dist/esm/components/LogCard.js +24 -22
  332. package/dist/esm/components/SkeletonPlaceholder.d.ts +3 -0
  333. package/dist/esm/components/SkeletonPlaceholder.js +42 -11
  334. package/dist/esm/constants/index.js +1 -1
  335. package/dist/esm/constants/telemetryConfig.d.ts +3 -3
  336. package/dist/esm/constants/telemetryConfig.js +1 -1
  337. package/dist/esm/constants/version.d.ts +1 -1
  338. package/dist/esm/constants/version.js +1 -1
  339. package/dist/esm/customHooks/crashHandler.d.ts +1 -1
  340. package/dist/esm/customHooks/crashHandler.js +6 -6
  341. package/dist/esm/customHooks/uiInspectorManager.d.ts +22 -0
  342. package/dist/esm/customHooks/uiInspectorManager.js +1 -0
  343. package/dist/esm/helpers/index.js +4 -6
  344. package/dist/esm/helpers/remoteConfig.js +1 -1
  345. package/dist/esm/helpers/searchQueryParser.d.ts +1 -0
  346. package/dist/esm/helpers/searchQueryParser.js +7 -5
  347. package/dist/esm/helpers/shareFormatter.d.ts +16 -0
  348. package/dist/esm/helpers/shareFormatter.js +20 -13
  349. package/dist/esm/helpers/uiInspectorEngine.d.ts +48 -0
  350. package/dist/esm/helpers/uiInspectorEngine.js +19 -0
  351. package/dist/esm/i18n/locales/ar.json +1 -1
  352. package/dist/esm/i18n/locales/bn.json +1 -1
  353. package/dist/esm/i18n/locales/de.json +1 -1
  354. package/dist/esm/i18n/locales/en.json +1 -1
  355. package/dist/esm/i18n/locales/es.json +1 -1
  356. package/dist/esm/i18n/locales/fr.json +1 -1
  357. package/dist/esm/i18n/locales/gu.json +1 -1
  358. package/dist/esm/i18n/locales/hi.json +1 -1
  359. package/dist/esm/i18n/locales/id.json +1 -1
  360. package/dist/esm/i18n/locales/it.json +1 -1
  361. package/dist/esm/i18n/locales/ja.json +1 -1
  362. package/dist/esm/i18n/locales/kn.json +1 -1
  363. package/dist/esm/i18n/locales/ko.json +1 -1
  364. package/dist/esm/i18n/locales/ml.json +1 -1
  365. package/dist/esm/i18n/locales/mr.json +1 -1
  366. package/dist/esm/i18n/locales/nl.json +1 -1
  367. package/dist/esm/i18n/locales/pa.json +1 -1
  368. package/dist/esm/i18n/locales/pl.json +1 -1
  369. package/dist/esm/i18n/locales/pt.json +1 -1
  370. package/dist/esm/i18n/locales/ru.json +1 -1
  371. package/dist/esm/i18n/locales/ta.json +1 -1
  372. package/dist/esm/i18n/locales/te.json +1 -1
  373. package/dist/esm/i18n/locales/tr.json +1 -1
  374. package/dist/esm/i18n/locales/vi.json +1 -1
  375. package/dist/esm/i18n/locales/zh.json +1 -1
  376. package/dist/esm/index.d.ts +4 -2
  377. package/dist/esm/index.js +8 -8
  378. package/dist/esm/native/NativeInspector.d.ts +4 -0
  379. package/dist/esm/native/NativeInspector.js +1 -1
  380. package/dist/esm/native/NativeNetworkInspector.d.ts +4 -0
  381. package/dist/esm/styles/AppFonts.d.ts +4 -0
  382. package/dist/esm/styles/AppFonts.js +1 -1
  383. package/dist/esm/styles/index.d.ts +2 -0
  384. package/dist/esm/styles/index.js +1 -1
  385. package/dist/esm/types/editor.d.ts +31 -0
  386. package/dist/esm/types/enums.d.ts +0 -2
  387. package/dist/esm/types/enums.js +1 -1
  388. package/dist/esm/types/interfaces.d.ts +1 -1
  389. package/ios/NetworkInspectorModule.mm +597 -336
  390. package/package.json +1 -1
  391. package/src/native/NativeInspector.ts +67 -0
  392. package/src/native/NativeNetworkInspector.ts +4 -0
@@ -10,8 +10,13 @@
10
10
  #import <CoreImage/CoreImage.h>
11
11
  #import <ImageIO/ImageIO.h>
12
12
  #import <MobileCoreServices/MobileCoreServices.h>
13
+ #import <Photos/Photos.h>
14
+ #import <PhotosUI/PhotosUI.h>
15
+ #if __has_include(<UniformTypeIdentifiers/UniformTypeIdentifiers.h>)
16
+ #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
17
+ #endif
13
18
 
14
- static NetworkInspectorModule *sharedInstance = nil;
19
+ static __weak NetworkInspectorModule *sharedInstance = nil;
15
20
  static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler = NULL;
16
21
  static BOOL g_floatingButtonPressed = NO;
17
22
 
@@ -322,38 +327,8 @@ static BOOL g_floatingButtonPressed = NO;
322
327
  static InAppInspectorFloatingView *floatingButtonView = nil;
323
328
  static BOOL g_floatingButtonDesiredVisible = NO;
324
329
 
325
- static void NativeSignalHandler(int signalNumber) {
326
- void* callstack[128];
327
- int frames = backtrace(callstack, 128);
328
- char **strs = backtrace_symbols(callstack, frames);
329
-
330
- NSMutableArray *backtraceArray = [NSMutableArray arrayWithCapacity:frames];
331
- for (int i = 0; i < frames; i++) {
332
- if (strs[i]) {
333
- [backtraceArray addObject:[NSString stringWithUTF8String:strs[i]]];
334
- }
335
- }
336
- free(strs);
337
-
338
- NSString *stackTrace = [backtraceArray componentsJoinedByString:@"\n"];
339
- NSString *signalName = @"UNKNOWN";
340
- switch (signalNumber) {
341
- case SIGABRT: signalName = @"SIGABRT (Abort)"; break;
342
- case SIGSEGV: signalName = @"SIGSEGV (Segmentation Fault)"; break;
343
- case SIGBUS: signalName = @"SIGBUS (Bus Error)"; break;
344
- case SIGILL: signalName = @"SIGILL (Illegal Instruction)"; break;
345
- case SIGFPE: signalName = @"SIGFPE (Floating Point Exception)"; break;
346
- case SIGPIPE: signalName = @"SIGPIPE (Broken Pipe)"; break;
347
- case SIGTRAP: signalName = @"SIGTRAP (Trace Trap)"; break;
348
- }
349
-
350
- NSString *message = [NSString stringWithFormat:@"Native Signal Crash: %@", signalName];
351
- if (sharedInstance != nil) {
352
- [sharedInstance emitCrashEventWithMessage:message stackTrace:stackTrace];
353
- }
354
- }
355
-
356
330
  static void NativeExceptionHandler(NSException *exception) {
331
+ if (!exception) return;
357
332
  NSArray *callStack = [exception callStackSymbols];
358
333
  NSString *stackTrace = [callStack componentsJoinedByString:@"\n"];
359
334
  NSString *message = [NSString stringWithFormat:@"%@: %@", [exception name], [exception reason]];
@@ -362,131 +337,35 @@ static void NativeExceptionHandler(NSException *exception) {
362
337
  [sharedInstance emitCrashEventWithMessage:message stackTrace:stackTrace];
363
338
  }
364
339
 
365
- // Give the crash event a brief window to emit (up to 3 seconds),
366
- // then delegate to the previous handler instead of freezing the UI forever.
367
- // The old infinite-runloop approach permanently froze the main thread on any
368
- // exception (including Fabric view recycling assertions), causing blank screens.
369
- CFRunLoopRef runLoop = CFRunLoopGetCurrent();
370
- CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
371
- NSTimeInterval deadline = [NSDate timeIntervalSinceReferenceDate] + 3.0;
372
- while ([NSDate timeIntervalSinceReferenceDate] < deadline) {
373
- for (NSString *mode in (__bridge NSArray *)allModes) {
374
- CFRunLoopRunInMode((CFStringRef)mode, 0.001, false);
375
- }
376
- }
377
- if (allModes) {
378
- CFRelease(allModes);
379
- }
340
+ // Save crash record to local cache directory synchronously for persistent debugging
341
+ @try {
342
+ NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
343
+ NSString *crashDir = [cacheDir stringByAppendingPathComponent:@"inspector_captures"];
344
+ [[NSFileManager defaultManager] createDirectoryAtPath:crashDir withIntermediateDirectories:YES attributes:nil error:nil];
345
+ NSString *crashFile = [crashDir stringByAppendingPathComponent:@"last_native_crash.json"];
346
+ NSDictionary *crashDict = @{
347
+ @"platform": @"ios",
348
+ @"message": message ?: @"Unknown iOS Exception",
349
+ @"name": [exception name] ?: @"NSException",
350
+ @"reason": [exception reason] ?: @"",
351
+ @"stack": stackTrace ?: @"",
352
+ @"timestamp": @([[NSDate date] timeIntervalSince1970] * 1000)
353
+ };
354
+ NSData *jsonData = [NSJSONSerialization dataWithJSONObject:crashDict options:NSJSONWritingPrettyPrinted error:nil];
355
+ [jsonData writeToFile:crashFile atomically:YES];
356
+ } @catch (NSException *e) {}
380
357
 
381
- // Delegate to the previous exception handler (e.g. React Native's own handler)
382
- if (previousUncaughtExceptionHandler) {
358
+ // Delegate to previous exception handler (React Native / Crashlytics / default)
359
+ if (previousUncaughtExceptionHandler && previousUncaughtExceptionHandler != &NativeExceptionHandler) {
383
360
  previousUncaughtExceptionHandler(exception);
384
361
  }
385
362
  }
386
363
 
387
- // ─── Fabric View Recycle Safeguard ───────────────────────────────────────────
388
- // Custom NSAssertionHandler that catches the specific Fabric view recycling
389
- // assertion ('Attempt to recycle a mounted view') and logs it as a warning
390
- // instead of crashing. This prevents third-party native views (like
391
- // BVLinearGradient from react-native-linear-gradient) from causing fatal
392
- // assertion failures when Fabric's view recycler encounters views whose
393
- // superview is still attached during conditional unmounting.
394
-
395
- @interface InAppInspectorAssertionHandler : NSAssertionHandler
396
- @property (nonatomic, strong) NSAssertionHandler *previousHandler;
397
- @end
398
-
399
- @implementation InAppInspectorAssertionHandler
400
-
401
- + (void)install {
402
- NSThread *mainThread = [NSThread mainThread];
403
- NSMutableDictionary *threadDict = [mainThread threadDictionary];
404
- NSAssertionHandler *current = threadDict[NSAssertionHandlerKey];
405
-
406
- InAppInspectorAssertionHandler *handler = [[InAppInspectorAssertionHandler alloc] init];
407
- handler.previousHandler = current;
408
- threadDict[NSAssertionHandlerKey] = handler;
409
- NSLog(@"[InAppInspector] Fabric view recycle safeguard (assertion handler) installed");
410
- }
411
-
412
- - (void)handleFailureInMethod:(SEL)selector
413
- object:(id)object
414
- file:(NSString *)fileName
415
- lineNumber:(NSInteger)line
416
- description:(NSString *)format, ... {
417
- va_list args;
418
- va_start(args, format);
419
- NSString *desc = [[NSString alloc] initWithFormat:format arguments:args];
420
- va_end(args);
421
-
422
- // Intercept the specific Fabric recycle assertion
423
- if ([desc containsString:@"Attempt to recycle a mounted view"]) {
424
- NSLog(@"[InAppInspector] ⚠️ Suppressed Fabric view recycle assertion: %@ (in %@:%ld)",
425
- desc, fileName, (long)line);
426
- return; // Suppress — don't crash
427
- }
428
-
429
- // Forward all other assertions to the previous handler
430
- if (self.previousHandler) {
431
- va_start(args, format);
432
- [self.previousHandler handleFailureInMethod:selector
433
- object:object
434
- file:fileName
435
- lineNumber:line
436
- description:@"%@", desc];
437
- va_end(args);
438
- } else {
439
- // No previous handler — raise as exception (default behavior)
440
- NSString *reason = [NSString stringWithFormat:
441
- @"*** Assertion failure in %@, %@:%ld: %@",
442
- NSStringFromSelector(selector), fileName, (long)line, desc];
443
- @throw [NSException exceptionWithName:NSInternalInconsistencyException
444
- reason:reason
445
- userInfo:nil];
446
- }
447
- }
448
-
449
- - (void)handleFailureInFunction:(NSString *)functionName
450
- file:(NSString *)fileName
451
- lineNumber:(NSInteger)line
452
- description:(NSString *)format, ... {
453
- va_list args;
454
- va_start(args, format);
455
- NSString *desc = [[NSString alloc] initWithFormat:format arguments:args];
456
- va_end(args);
457
-
458
- // Intercept the specific Fabric recycle assertion
459
- if ([desc containsString:@"Attempt to recycle a mounted view"]) {
460
- NSLog(@"[InAppInspector] ⚠️ Suppressed Fabric view recycle assertion: %@ (in %@:%ld)",
461
- desc, fileName, (long)line);
462
- return; // Suppress — don't crash
463
- }
464
-
465
- // Forward all other assertions to the previous handler
466
- if (self.previousHandler) {
467
- va_start(args, format);
468
- [self.previousHandler handleFailureInFunction:functionName
469
- file:fileName
470
- lineNumber:line
471
- description:@"%@", desc];
472
- va_end(args);
473
- } else {
474
- NSString *reason = [NSString stringWithFormat:
475
- @"*** Assertion failure in %@, %@:%ld: %@",
476
- functionName, fileName, (long)line, desc];
477
- @throw [NSException exceptionWithName:NSInternalInconsistencyException
478
- reason:reason
479
- userInfo:nil];
480
- }
481
- }
482
-
483
- @end
484
-
485
364
  // ─────────────────────────────────────────────────────────────────────────────
486
365
  // NATIVE CAMERA ROLL / PHOTO & VIDEO PICKER DELEGATE
487
366
  // ─────────────────────────────────────────────────────────────────────────────
488
367
 
489
- @interface InAppInspectorPickerDelegate : NSObject <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
368
+ @interface InAppInspectorPickerDelegate : NSObject <PHPickerViewControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
490
369
  @property (nonatomic, copy) RCTPromiseResolveBlock resolve;
491
370
  @property (nonatomic, copy) RCTPromiseRejectBlock reject;
492
371
  @property (nonatomic, copy) NSString *capturesDirectory;
@@ -494,18 +373,18 @@ static void NativeExceptionHandler(NSException *exception) {
494
373
 
495
374
  @implementation InAppInspectorPickerDelegate
496
375
 
497
- - (void)picker:(id)picker didFinishPicking:(NSArray *)results {
376
+ - (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14.0)) {
498
377
  [picker dismissViewControllerAnimated:YES completion:nil];
499
378
  if (results.count == 0) {
500
379
  if (self.resolve) self.resolve([NSNull null]);
501
380
  return;
502
381
  }
503
-
504
- id result = results.firstObject;
505
- NSItemProvider *provider = [result valueForKey:@"itemProvider"];
382
+
383
+ PHPickerResult *result = results.firstObject;
384
+ NSItemProvider *provider = result.itemProvider;
506
385
  long long timestamp = (long long)([[NSDate date] timeIntervalSince1970] * 1000.0);
507
386
  NSString *randomStr = [NSString stringWithFormat:@"%04d", arc4random_uniform(10000)];
508
-
387
+
509
388
  if ([provider hasItemConformingToTypeIdentifier:@"public.movie"]) {
510
389
  [provider loadFileRepresentationForTypeIdentifier:@"public.movie" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
511
390
  if (error || !url) {
@@ -516,13 +395,13 @@ static void NativeExceptionHandler(NSException *exception) {
516
395
  if (ext.length == 0) ext = @"mp4";
517
396
  NSString *filename = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@.%@", timestamp, randomStr, ext];
518
397
  NSString *destPath = [self.capturesDirectory stringByAppendingPathComponent:filename];
519
-
398
+
520
399
  [[NSFileManager defaultManager] removeItemAtPath:destPath error:nil];
521
400
  [[NSFileManager defaultManager] copyItemAtURL:url toURL:[NSURL fileURLWithPath:destPath] error:nil];
522
-
401
+
523
402
  NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destPath error:nil];
524
403
  long long sizeBytes = [attrs fileSize];
525
-
404
+
526
405
  NSMutableDictionary *map = [NSMutableDictionary dictionaryWithDictionary:@{
527
406
  @"id": filename,
528
407
  @"type": @"video",
@@ -532,7 +411,7 @@ static void NativeExceptionHandler(NSException *exception) {
532
411
  @"sizeBytes": @(sizeBytes),
533
412
  @"timestamp": @(timestamp)
534
413
  }];
535
-
414
+
536
415
  @try {
537
416
  AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[NSURL fileURLWithPath:destPath] options:nil];
538
417
  AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset];
@@ -548,7 +427,7 @@ static void NativeExceptionHandler(NSException *exception) {
548
427
  map[@"thumbnailUri"] = [NSURL fileURLWithPath:thumbPath].absoluteString;
549
428
  }
550
429
  } @catch (id ex) {}
551
-
430
+
552
431
  if (self.resolve) self.resolve(map);
553
432
  }];
554
433
  } else {
@@ -559,12 +438,12 @@ static void NativeExceptionHandler(NSException *exception) {
559
438
  NSString *type = [ext isEqualToString:@"gif"] ? @"gif" : @"image";
560
439
  NSString *filename = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@.%@", timestamp, randomStr, ext];
561
440
  NSString *destPath = [self.capturesDirectory stringByAppendingPathComponent:filename];
562
-
441
+
563
442
  [[NSFileManager defaultManager] removeItemAtPath:destPath error:nil];
564
443
  [[NSFileManager defaultManager] copyItemAtURL:url toURL:[NSURL fileURLWithPath:destPath] error:nil];
565
444
  NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destPath error:nil];
566
445
  long long sizeBytes = [attrs fileSize];
567
-
446
+
568
447
  NSDictionary *map = @{
569
448
  @"id": filename,
570
449
  @"type": type,
@@ -583,10 +462,10 @@ static void NativeExceptionHandler(NSException *exception) {
583
462
  NSString *filename = [NSString stringWithFormat:@"rn_iai_%lld_imported_%@.jpg", timestamp, randomStr];
584
463
  NSString *destPath = [self.capturesDirectory stringByAppendingPathComponent:filename];
585
464
  [data writeToFile:destPath atomically:YES];
586
-
465
+
587
466
  NSDictionary *attrs = [[NSFileManager defaultManager] attributesOfItemAtPath:destPath error:nil];
588
467
  long long sizeBytes = [attrs fileSize];
589
-
468
+
590
469
  NSDictionary *map = @{
591
470
  @"id": filename,
592
471
  @"type": @"image",
@@ -620,6 +499,139 @@ static void NativeExceptionHandler(NSException *exception) {
620
499
 
621
500
  static InAppInspectorPickerDelegate *g_pickerDelegate = nil;
622
501
 
502
+ // ─────────────────────────────────────────────────────────────────────────────
503
+ // SAFE WINDOW & VIEW CONTROLLER HELPERS (iOS 13 - 18+)
504
+ // ─────────────────────────────────────────────────────────────────────────────
505
+
506
+ static BOOL IsInternalSystemWindow(UIWindow *w) {
507
+ if (!w) return YES;
508
+ NSString *className = NSStringFromClass([w class]);
509
+ if ([className hasPrefix:@"_"] ||
510
+ [className containsString:@"Keyboard"] ||
511
+ [className containsString:@"TextEffect"] ||
512
+ [className containsString:@"StatusBar"] ||
513
+ [className containsString:@"InputSet"] ||
514
+ [className containsString:@"TrackingWindow"]) {
515
+ return YES;
516
+ }
517
+ return NO;
518
+ }
519
+
520
+ static UIWindow *GetAppActiveWindow(void) {
521
+ if (@available(iOS 13.0, *)) {
522
+ // Priority 1: Foreground Active Scene with Key Window
523
+ for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
524
+ if ([scene isKindOfClass:[UIWindowScene class]] && scene.activationState == UISceneActivationStateForegroundActive) {
525
+ UIWindowScene *ws = (UIWindowScene *)scene;
526
+ for (UIWindow *w in ws.windows) {
527
+ if (w.isKeyWindow && !w.hidden && w.alpha > 0.01 && !IsInternalSystemWindow(w)) {
528
+ return w;
529
+ }
530
+ }
531
+ for (UIWindow *w in ws.windows) {
532
+ if (w.windowLevel == UIWindowLevelNormal && !w.hidden && w.alpha > 0.01 && !IsInternalSystemWindow(w)) {
533
+ return w;
534
+ }
535
+ }
536
+ }
537
+ }
538
+ // Priority 2: Any Scene with usable window
539
+ for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
540
+ if ([scene isKindOfClass:[UIWindowScene class]]) {
541
+ UIWindowScene *ws = (UIWindowScene *)scene;
542
+ for (UIWindow *w in ws.windows) {
543
+ if (!w.hidden && w.alpha > 0.01 && !IsInternalSystemWindow(w) && (w.isKeyWindow || w.windowLevel == UIWindowLevelNormal)) {
544
+ return w;
545
+ }
546
+ }
547
+ if (ws.windows.count > 0 && !IsInternalSystemWindow(ws.windows.firstObject)) {
548
+ return ws.windows.firstObject;
549
+ }
550
+ }
551
+ }
552
+ }
553
+ #pragma clang diagnostic push
554
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
555
+ for (UIWindow *w in [UIApplication sharedApplication].windows) {
556
+ if (!IsInternalSystemWindow(w) && (w.isKeyWindow || w.windowLevel == UIWindowLevelNormal)) {
557
+ return w;
558
+ }
559
+ }
560
+ return [UIApplication sharedApplication].windows.firstObject;
561
+ #pragma clang diagnostic pop
562
+ }
563
+
564
+ static UIViewController *FindTopViewControllerFrom(UIViewController *vc) {
565
+ if (!vc) return nil;
566
+ if ([vc isKindOfClass:[UINavigationController class]]) {
567
+ UIViewController *visible = [(UINavigationController *)vc visibleViewController];
568
+ return visible ? FindTopViewControllerFrom(visible) : vc;
569
+ }
570
+ if ([vc isKindOfClass:[UITabBarController class]]) {
571
+ UIViewController *selected = [(UITabBarController *)vc selectedViewController];
572
+ return selected ? FindTopViewControllerFrom(selected) : vc;
573
+ }
574
+ if (vc.presentedViewController && !vc.presentedViewController.isBeingDismissed) {
575
+ return FindTopViewControllerFrom(vc.presentedViewController);
576
+ }
577
+ return vc;
578
+ }
579
+
580
+ static UIViewController *GetTopViewController(void) {
581
+ UIWindow *win = GetAppActiveWindow();
582
+ UIViewController *root = win ? win.rootViewController : nil;
583
+ if (!root) {
584
+ if ([[UIApplication sharedApplication].delegate respondsToSelector:@selector(window)]) {
585
+ root = [UIApplication sharedApplication].delegate.window.rootViewController;
586
+ }
587
+ }
588
+ return root ? FindTopViewControllerFrom(root) : nil;
589
+ }
590
+
591
+ static CGRect GetAppScreenBounds(void) {
592
+ UIWindow *w = GetAppActiveWindow();
593
+ if (w && w.bounds.size.width > 0 && w.bounds.size.height > 0) {
594
+ return w.bounds;
595
+ }
596
+ if (@available(iOS 13.0, *)) {
597
+ for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
598
+ if ([scene isKindOfClass:[UIWindowScene class]]) {
599
+ UIWindowScene *ws = (UIWindowScene *)scene;
600
+ if (ws.coordinateSpace.bounds.size.width > 0 && ws.coordinateSpace.bounds.size.height > 0) {
601
+ return ws.coordinateSpace.bounds;
602
+ }
603
+ }
604
+ }
605
+ }
606
+ #pragma clang diagnostic push
607
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
608
+ CGRect b = [UIScreen mainScreen].bounds;
609
+ if (b.size.width > 0 && b.size.height > 0) return b;
610
+ #pragma clang diagnostic pop
611
+ return CGRectMake(0, 0, 393, 852);
612
+ }
613
+
614
+ static CGFloat GetAppScreenScale(void) {
615
+ UIWindow *w = GetAppActiveWindow();
616
+ if (w && w.screen) {
617
+ return w.screen.scale;
618
+ }
619
+ if (@available(iOS 13.0, *)) {
620
+ for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
621
+ if ([scene isKindOfClass:[UIWindowScene class]]) {
622
+ UIWindowScene *ws = (UIWindowScene *)scene;
623
+ if (ws.screen) {
624
+ return ws.screen.scale;
625
+ }
626
+ }
627
+ }
628
+ }
629
+ #pragma clang diagnostic push
630
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
631
+ return [UIScreen mainScreen].scale > 0 ? [UIScreen mainScreen].scale : 2.0;
632
+ #pragma clang diagnostic pop
633
+ }
634
+
623
635
  @implementation NetworkInspectorModule {
624
636
  bool hasListeners;
625
637
  CADisplayLink *displayLink;
@@ -675,6 +687,17 @@ RCT_EXPORT_MODULE(NetworkInspectorModule);
675
687
  return self;
676
688
  }
677
689
 
690
+ - (void)dealloc {
691
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
692
+ if (self->displayLink) {
693
+ [self->displayLink invalidate];
694
+ self->displayLink = nil;
695
+ }
696
+ if (sharedInstance == self) {
697
+ sharedInstance = nil;
698
+ }
699
+ }
700
+
678
701
  + (BOOL)requiresMainQueueSetup {
679
702
  return YES;
680
703
  }
@@ -696,7 +719,6 @@ RCT_EXPORT_MODULE(NetworkInspectorModule);
696
719
 
697
720
  - (void)safeSendEvent:(NSString *)eventName body:(id)body {
698
721
  if (!hasListeners) return;
699
- if (self.bridge == nil) return;
700
722
  @try {
701
723
  [self sendEventWithName:eventName body:body];
702
724
  } @catch (NSException *ex) {
@@ -721,33 +743,13 @@ RCT_EXPORT_MODULE(NetworkInspectorModule);
721
743
  }
722
744
 
723
745
  - (void)installHandlers {
724
- previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
725
- NSSetUncaughtExceptionHandler(&NativeExceptionHandler);
726
-
727
- struct sigaction sa;
728
- sa.sa_handler = NativeSignalHandler;
729
- sigemptyset(&sa.sa_mask);
730
- sa.sa_flags = SA_NODEFER;
731
-
732
- sigaction(SIGABRT, &sa, NULL);
733
- sigaction(SIGSEGV, &sa, NULL);
734
- sigaction(SIGBUS, &sa, NULL);
735
- sigaction(SIGILL, &sa, NULL);
736
- sigaction(SIGFPE, &sa, NULL);
737
- sigaction(SIGPIPE, &sa, NULL);
738
- sigaction(SIGTRAP, &sa, NULL);
739
-
740
- // Fabric view recycle safeguard: Install a custom NSAssertionHandler on the
741
- // main thread that catches the specific 'Attempt to recycle a mounted view'
742
- // assertion from RCTComponentViewRegistry, instead of crashing the app.
743
- // This is a defense-in-depth approach — the primary fix is on the JS side
744
- // (using LinearGradient as absolute background, not as a container parent).
745
- static dispatch_once_t onceToken;
746
- dispatch_once(&onceToken, ^{
747
- dispatch_async(dispatch_get_main_queue(), ^{
748
- [InAppInspectorAssertionHandler install];
749
- });
750
- });
746
+ @try {
747
+ if (!previousUncaughtExceptionHandler) {
748
+ previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
749
+ NSSetUncaughtExceptionHandler(&NativeExceptionHandler);
750
+ }
751
+ signal(SIGPIPE, SIG_IGN);
752
+ } @catch (NSException *e) {}
751
753
  }
752
754
 
753
755
  - (void)emitCrashEventWithMessage:(NSString *)message stackTrace:(NSString *)stackTrace {
@@ -766,6 +768,41 @@ RCT_EXPORT_METHOD(enableNativeCrashProtection:(RCTPromiseResolveBlock)resolve
766
768
  resolve(@(YES));
767
769
  }
768
770
 
771
+ RCT_EXPORT_METHOD(getLastNativeCrash:(RCTPromiseResolveBlock)resolve
772
+ reject:(RCTPromiseRejectBlock)reject) {
773
+ @try {
774
+ NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
775
+ NSString *crashFile = [[cacheDir stringByAppendingPathComponent:@"inspector_captures"] stringByAppendingPathComponent:@"last_native_crash.json"];
776
+ if ([[NSFileManager defaultManager] fileExistsAtPath:crashFile]) {
777
+ NSData *data = [NSData dataWithContentsOfFile:crashFile];
778
+ if (data) {
779
+ NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
780
+ if (json) {
781
+ resolve(json);
782
+ return;
783
+ }
784
+ }
785
+ }
786
+ resolve([NSNull null]);
787
+ } @catch (NSException *e) {
788
+ reject(@"GET_CRASH_ERROR", e.reason, nil);
789
+ }
790
+ }
791
+
792
+ RCT_EXPORT_METHOD(clearLastNativeCrash:(RCTPromiseResolveBlock)resolve
793
+ reject:(RCTPromiseRejectBlock)reject) {
794
+ @try {
795
+ NSString *cacheDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
796
+ NSString *crashFile = [[cacheDir stringByAppendingPathComponent:@"inspector_captures"] stringByAppendingPathComponent:@"last_native_crash.json"];
797
+ if ([[NSFileManager defaultManager] fileExistsAtPath:crashFile]) {
798
+ [[NSFileManager defaultManager] removeItemAtPath:crashFile error:nil];
799
+ }
800
+ resolve(@(YES));
801
+ } @catch (NSException *e) {
802
+ reject(@"CLEAR_CRASH_ERROR", e.reason, nil);
803
+ }
804
+ }
805
+
769
806
  RCT_EXPORT_METHOD(getDeviceMetrics:(RCTPromiseResolveBlock)resolve
770
807
  reject:(RCTPromiseRejectBlock)reject) {
771
808
  NSMutableDictionary *metrics = [NSMutableDictionary dictionary];
@@ -837,42 +874,15 @@ RCT_EXPORT_METHOD(getDeviceMetrics:(RCTPromiseResolveBlock)resolve
837
874
  resolve(metrics);
838
875
  }
839
876
 
840
- static UIWindow *GetAppActiveWindow(void) {
841
- if (@available(iOS 13.0, *)) {
842
- for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
843
- if ([scene isKindOfClass:[UIWindowScene class]]) {
844
- UIWindowScene *ws = (UIWindowScene *)scene;
845
- for (UIWindow *w in ws.windows) {
846
- if (w.isKeyWindow || w.windowLevel == UIWindowLevelNormal) {
847
- return w;
848
- }
849
- }
850
- if (ws.windows.count > 0) {
851
- return ws.windows.firstObject;
852
- }
853
- }
854
- }
855
- }
856
- for (UIWindow *w in [UIApplication sharedApplication].windows) {
857
- if (w.isKeyWindow || w.windowLevel == UIWindowLevelNormal) {
858
- return w;
859
- }
860
- }
861
- return [UIApplication sharedApplication].windows.firstObject;
862
- }
863
-
864
877
  RCT_EXPORT_METHOD(showFloatingButton:(NSDictionary *)options
865
878
  resolve:(RCTPromiseResolveBlock)resolve
866
879
  reject:(RCTPromiseRejectBlock)reject) {
867
880
  dispatch_async(dispatch_get_main_queue(), ^{
868
881
  g_floatingButtonDesiredVisible = YES;
869
- UIWindow *targetWindow = GetAppActiveWindow();
870
- CGRect screenBounds = targetWindow ? targetWindow.bounds : [UIScreen mainScreen].bounds;
882
+ CGRect screenBounds = GetAppScreenBounds();
871
883
 
872
- CGFloat screenWidth = screenBounds.size.width > 0 ? screenBounds.size.width : [UIScreen mainScreen].bounds.size.width;
873
- if (screenWidth <= 0) screenWidth = 393.0;
874
- CGFloat screenHeight = screenBounds.size.height > 0 ? screenBounds.size.height : [UIScreen mainScreen].bounds.size.height;
875
- if (screenHeight <= 0) screenHeight = 852.0;
884
+ CGFloat screenWidth = screenBounds.size.width > 0 ? screenBounds.size.width : 393.0;
885
+ CGFloat screenHeight = screenBounds.size.height > 0 ? screenBounds.size.height : 852.0;
876
886
 
877
887
  CGFloat size = 64.0;
878
888
  if (options && options[@"size"]) {
@@ -1271,32 +1281,7 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1271
1281
  }
1272
1282
 
1273
1283
  - (UIWindow *)findActiveKeyWindow {
1274
- UIWindow *foundWindow = nil;
1275
- if (@available(iOS 13.0, *)) {
1276
- for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
1277
- if ([scene isKindOfClass:[UIWindowScene class]]) {
1278
- UIWindowScene *windowScene = (UIWindowScene *)scene;
1279
- for (UIWindow *w in windowScene.windows) {
1280
- if (w.isKeyWindow) {
1281
- return w;
1282
- }
1283
- if (!foundWindow && !w.hidden && w.alpha > 0.01) {
1284
- foundWindow = w;
1285
- }
1286
- }
1287
- }
1288
- }
1289
- }
1290
- if (!foundWindow) {
1291
- #pragma clang diagnostic push
1292
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
1293
- foundWindow = [UIApplication sharedApplication].keyWindow;
1294
- if (!foundWindow && [UIApplication sharedApplication].windows.count > 0) {
1295
- foundWindow = [UIApplication sharedApplication].windows.firstObject;
1296
- }
1297
- #pragma clang diagnostic pop
1298
- }
1299
- return foundWindow;
1284
+ return GetAppActiveWindow();
1300
1285
  }
1301
1286
 
1302
1287
  - (UIImage *)captureScreenHierarchyWithScale:(CGFloat)scale {
@@ -1305,10 +1290,13 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1305
1290
  return nil;
1306
1291
  }
1307
1292
 
1308
- CGRect screenBounds = [UIScreen mainScreen].bounds;
1309
- CGFloat screenScale = [UIScreen mainScreen].scale;
1293
+ CGRect screenBounds = GetAppScreenBounds();
1294
+ CGFloat screenScale = GetAppScreenScale();
1310
1295
  CGFloat finalScale = screenScale * scale;
1311
1296
  if (finalScale <= 0.0) finalScale = screenScale;
1297
+ if (screenBounds.size.width <= 0 || screenBounds.size.height <= 0) {
1298
+ screenBounds = CGRectMake(0, 0, 393, 852);
1299
+ }
1312
1300
 
1313
1301
  UIGraphicsBeginImageContextWithOptions(screenBounds.size, NO, finalScale);
1314
1302
  CGContextRef context = UIGraphicsGetCurrentContext();
@@ -1338,7 +1326,7 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1338
1326
 
1339
1327
  BOOL drewAny = NO;
1340
1328
  for (UIWindow *w in sortedWindows) {
1341
- if (w.hidden || w.alpha <= 0.01 || w.bounds.size.width <= 0) continue;
1329
+ if (w.hidden || w.alpha <= 0.01 || w.bounds.size.width <= 0 || IsInternalSystemWindow(w)) continue;
1342
1330
  @try {
1343
1331
  BOOL ok = [w drawViewHierarchyInRect:w.bounds afterScreenUpdates:NO];
1344
1332
  if (ok) {
@@ -1422,8 +1410,8 @@ RCT_EXPORT_METHOD(getNativeCachedPage:(NSString *)pageKey
1422
1410
  resolve:(RCTPromiseResolveBlock)resolve
1423
1411
  reject:(RCTPromiseRejectBlock)reject {
1424
1412
  dispatch_async(dispatch_get_main_queue(), ^{
1425
- CGRect bounds = [UIScreen mainScreen].bounds;
1426
- CGFloat screenScale = [UIScreen mainScreen].scale;
1413
+ CGRect bounds = GetAppScreenBounds();
1414
+ CGFloat screenScale = GetAppScreenScale();
1427
1415
  double scaleParam = [options[@"scale"] doubleValue];
1428
1416
  if (scaleParam <= 0.0 || scaleParam > 1.0) {
1429
1417
  scaleParam = 0.5;
@@ -1764,15 +1752,7 @@ RCT_EXPORT_METHOD(playVideo:(NSString *)videoUri
1764
1752
  playerController.showsPlaybackControls = YES;
1765
1753
  playerController.modalPresentationStyle = UIModalPresentationFullScreen;
1766
1754
 
1767
- UIWindow *keyWindow = [self findActiveKeyWindow];
1768
- UIViewController *rootVC = keyWindow.rootViewController;
1769
- if (!rootVC) {
1770
- rootVC = [UIApplication sharedApplication].delegate.window.rootViewController;
1771
- }
1772
- while (rootVC.presentedViewController) {
1773
- rootVC = rootVC.presentedViewController;
1774
- }
1775
-
1755
+ UIViewController *rootVC = GetTopViewController();
1776
1756
  if (rootVC) {
1777
1757
  [rootVC presentViewController:playerController animated:YES completion:^{
1778
1758
  [player play];
@@ -1825,7 +1805,7 @@ RCT_EXPORT_METHOD(convertToGif:(NSString *)videoUri
1825
1805
  NSString *filePath = [[self getCapturesDirectory] stringByAppendingPathComponent:filename];
1826
1806
  NSURL *gifUrl = [NSURL fileURLWithPath:filePath];
1827
1807
 
1828
- CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)gifUrl, kUTTypeGIF, 0, NULL);
1808
+ CGImageDestinationRef destination = CGImageDestinationCreateWithURL((__bridge CFURLRef)gifUrl, (CFStringRef)@"com.compuserve.gif", 0, NULL);
1829
1809
  if (!destination) {
1830
1810
  reject(@"GIF_ERROR", @"Failed to create GIF image destination", nil);
1831
1811
  return;
@@ -2085,6 +2065,36 @@ RCT_EXPORT_METHOD(clearAllCapturedMedia:(RCTPromiseResolveBlock)resolve
2085
2065
  // 100% Native Media Editor: Photo Editing (CoreImage + ImageIO)
2086
2066
  // ─────────────────────────────────────────────────────────────────────────────
2087
2067
 
2068
+ static UIColor *inspectorColorFromHex(NSString *hexString, UIColor *defaultColor) {
2069
+ if (!hexString || ![hexString isKindOfClass:[NSString class]]) {
2070
+ return defaultColor ?: [UIColor redColor];
2071
+ }
2072
+ NSString *cleanHex = [hexString stringByReplacingOccurrencesOfString:@"#" withString:@""];
2073
+ cleanHex = [cleanHex stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
2074
+ unsigned int rgbValue = 0;
2075
+ NSScanner *scanner = [NSScanner scannerWithString:cleanHex];
2076
+ [scanner scanHexInt:&rgbValue];
2077
+
2078
+ if (cleanHex.length == 8) {
2079
+ CGFloat r = ((rgbValue & 0xFF000000) >> 24) / 255.0;
2080
+ CGFloat g = ((rgbValue & 0x00FF0000) >> 16) / 255.0;
2081
+ CGFloat b = ((rgbValue & 0x0000FF00) >> 8) / 255.0;
2082
+ CGFloat a = (rgbValue & 0x000000FF) / 255.0;
2083
+ return [UIColor colorWithRed:r green:g blue:b alpha:a];
2084
+ } else if (cleanHex.length == 6) {
2085
+ CGFloat r = ((rgbValue & 0xFF0000) >> 16) / 255.0;
2086
+ CGFloat g = ((rgbValue & 0x00FF00) >> 8) / 255.0;
2087
+ CGFloat b = (rgbValue & 0x0000FF) / 255.0;
2088
+ return [UIColor colorWithRed:r green:g blue:b alpha:1.0];
2089
+ } else if (cleanHex.length == 3) {
2090
+ CGFloat r = (((rgbValue & 0xF00) >> 8) * 17) / 255.0;
2091
+ CGFloat g = (((rgbValue & 0x0F0) >> 4) * 17) / 255.0;
2092
+ CGFloat b = ((rgbValue & 0x00F) * 17) / 255.0;
2093
+ return [UIColor colorWithRed:r green:g blue:b alpha:1.0];
2094
+ }
2095
+ return defaultColor ?: [UIColor redColor];
2096
+ }
2097
+
2088
2098
  RCT_EXPORT_METHOD(editPhoto:(NSDictionary *)options
2089
2099
  resolve:(RCTPromiseResolveBlock)resolve
2090
2100
  reject:(RCTPromiseRejectBlock)reject) {
@@ -2245,34 +2255,223 @@ RCT_EXPORT_METHOD(editPhoto:(NSDictionary *)options
2245
2255
  UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
2246
2256
  CGImageRelease(cgImage);
2247
2257
 
2248
- // 7. Apply Redactions & Annotations Overlay if provided
2258
+ // 7. Apply Redactions, Freehand Drawings, Draggable Texts & Annotations Overlay if provided
2249
2259
  NSArray *redactions = options[@"redactions"];
2250
2260
  NSArray *annotations = options[@"annotations"];
2251
- if ((redactions && [redactions isKindOfClass:[NSArray class]] && redactions.count > 0) ||
2252
- (annotations && [annotations isKindOfClass:[NSArray class]] && annotations.count > 0)) {
2261
+ NSArray *drawings = options[@"drawings"];
2262
+ NSArray *texts = options[@"texts"];
2263
+
2264
+ BOOL hasOverlay = (redactions && [redactions isKindOfClass:[NSArray class]] && redactions.count > 0) ||
2265
+ (annotations && [annotations isKindOfClass:[NSArray class]] && annotations.count > 0) ||
2266
+ (drawings && [drawings isKindOfClass:[NSArray class]] && drawings.count > 0) ||
2267
+ (texts && [texts isKindOfClass:[NSArray class]] && texts.count > 0);
2268
+
2269
+ if (hasOverlay) {
2253
2270
  UIGraphicsBeginImageContextWithOptions(resultImage.size, NO, 1.0);
2254
2271
  [resultImage drawInRect:CGRectMake(0, 0, resultImage.size.width, resultImage.size.height)];
2255
2272
  CGContextRef ctx = UIGraphicsGetCurrentContext();
2256
2273
 
2274
+ CGFloat canvasW = resultImage.size.width;
2275
+ CGFloat canvasH = resultImage.size.height;
2276
+ CGFloat baseScale = MAX(1.0, canvasW / 380.0);
2277
+
2278
+ // A. Redactions (Blackout or Blur/Pixelate Box)
2257
2279
  if (redactions && [redactions isKindOfClass:[NSArray class]]) {
2258
2280
  for (NSDictionary *box in redactions) {
2259
2281
  CGFloat x = [box[@"x"] doubleValue];
2260
2282
  CGFloat y = [box[@"y"] doubleValue];
2261
2283
  CGFloat w = [box[@"width"] doubleValue];
2262
2284
  CGFloat h = [box[@"height"] doubleValue];
2263
- BOOL isNorm = [box[@"isNormalized"] boolValue];
2285
+ BOOL isNorm = box[@"isNormalized"] ? [box[@"isNormalized"] boolValue] : YES;
2264
2286
  if (isNorm) {
2265
- x *= resultImage.size.width;
2266
- y *= resultImage.size.height;
2267
- w *= resultImage.size.width;
2268
- h *= resultImage.size.height;
2287
+ x *= canvasW;
2288
+ y *= canvasH;
2289
+ w *= canvasW;
2290
+ h *= canvasH;
2291
+ }
2292
+ NSString *style = box[@"style"] ?: @"blackout";
2293
+ if ([style isEqualToString:@"blur"] || [style isEqualToString:@"pixelate"]) {
2294
+ CGContextSetFillColorWithColor(ctx, [UIColor colorWithWhite:0.12 alpha:0.92].CGColor);
2295
+ } else {
2296
+ CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
2269
2297
  }
2270
- CGContextSetFillColorWithColor(ctx, [UIColor blackColor].CGColor);
2271
2298
  CGContextFillRect(ctx, CGRectMake(x, y, w, h));
2272
2299
  }
2273
2300
  }
2274
2301
 
2275
- if (annotations && [annotations isKindOfClass:[NSArray class]]) {
2302
+ // B. Freehand Drawings & Vector Shapes (Brush, Highlighter, Arrow, Rect, Circle, Step)
2303
+ if (drawings && [drawings isKindOfClass:[NSArray class]]) {
2304
+ for (NSDictionary *stroke in drawings) {
2305
+ NSString *type = stroke[@"type"] ?: @"brush";
2306
+ NSString *hexColor = stroke[@"color"] ?: @"#EF4444";
2307
+ UIColor *strokeColor = inspectorColorFromHex(hexColor, [UIColor redColor]);
2308
+ CGFloat strokeWidth = stroke[@"strokeWidth"] ? [stroke[@"strokeWidth"] doubleValue] * baseScale : 4.0 * baseScale;
2309
+ BOOL isNorm = stroke[@"isNormalized"] ? [stroke[@"isNormalized"] boolValue] : YES;
2310
+ NSArray *points = stroke[@"points"];
2311
+
2312
+ if ([type isEqualToString:@"brush"]) {
2313
+ if (points && points.count > 1) {
2314
+ CGContextSetStrokeColorWithColor(ctx, strokeColor.CGColor);
2315
+ CGContextSetLineWidth(ctx, strokeWidth);
2316
+ CGContextSetLineCap(ctx, kCGLineCapRound);
2317
+ CGContextSetLineJoin(ctx, kCGLineJoinRound);
2318
+ CGContextBeginPath(ctx);
2319
+ for (NSUInteger pIdx = 0; pIdx < points.count; pIdx++) {
2320
+ NSDictionary *pt = points[pIdx];
2321
+ CGFloat px = [pt[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2322
+ CGFloat py = [pt[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2323
+ if (pIdx == 0) {
2324
+ CGContextMoveToPoint(ctx, px, py);
2325
+ } else {
2326
+ CGContextAddLineToPoint(ctx, px, py);
2327
+ }
2328
+ }
2329
+ CGContextStrokePath(ctx);
2330
+ }
2331
+ } else if ([type isEqualToString:@"highlighter"]) {
2332
+ if (points && points.count > 1) {
2333
+ UIColor *hiColor = [strokeColor colorWithAlphaComponent:0.4];
2334
+ CGContextSetStrokeColorWithColor(ctx, hiColor.CGColor);
2335
+ CGContextSetLineWidth(ctx, strokeWidth * 2.5);
2336
+ CGContextSetLineCap(ctx, kCGLineCapRound);
2337
+ CGContextSetLineJoin(ctx, kCGLineJoinRound);
2338
+ CGContextBeginPath(ctx);
2339
+ for (NSUInteger pIdx = 0; pIdx < points.count; pIdx++) {
2340
+ NSDictionary *pt = points[pIdx];
2341
+ CGFloat px = [pt[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2342
+ CGFloat py = [pt[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2343
+ if (pIdx == 0) {
2344
+ CGContextMoveToPoint(ctx, px, py);
2345
+ } else {
2346
+ CGContextAddLineToPoint(ctx, px, py);
2347
+ }
2348
+ }
2349
+ CGContextStrokePath(ctx);
2350
+ }
2351
+ } else if ([type isEqualToString:@"arrow"]) {
2352
+ if (points && points.count >= 2) {
2353
+ NSDictionary *p0 = points[0];
2354
+ NSDictionary *p1 = points[points.count - 1];
2355
+ CGFloat x0 = [p0[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2356
+ CGFloat y0 = [p0[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2357
+ CGFloat x1 = [p1[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2358
+ CGFloat y1 = [p1[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2359
+
2360
+ CGContextSetStrokeColorWithColor(ctx, strokeColor.CGColor);
2361
+ CGContextSetLineWidth(ctx, strokeWidth);
2362
+ CGContextSetLineCap(ctx, kCGLineCapRound);
2363
+ CGContextBeginPath(ctx);
2364
+ CGContextMoveToPoint(ctx, x0, y0);
2365
+ CGContextAddLineToPoint(ctx, x1, y1);
2366
+ CGContextStrokePath(ctx);
2367
+
2368
+ CGFloat dx = x1 - x0;
2369
+ CGFloat dy = y1 - y0;
2370
+ CGFloat angle = atan2(dy, dx);
2371
+ CGFloat headLen = MAX(14.0 * baseScale, MIN(32.0 * baseScale, strokeWidth * 3.5));
2372
+ CGFloat headAngle = M_PI / 6.0;
2373
+ CGFloat ax1 = x1 - headLen * cos(angle - headAngle);
2374
+ CGFloat ay1 = y1 - headLen * sin(angle - headAngle);
2375
+ CGFloat ax2 = x1 - headLen * cos(angle + headAngle);
2376
+ CGFloat ay2 = y1 - headLen * sin(angle + headAngle);
2377
+
2378
+ CGContextSetFillColorWithColor(ctx, strokeColor.CGColor);
2379
+ CGContextBeginPath(ctx);
2380
+ CGContextMoveToPoint(ctx, x1, y1);
2381
+ CGContextAddLineToPoint(ctx, ax1, ay1);
2382
+ CGContextAddLineToPoint(ctx, ax2, ay2);
2383
+ CGContextClosePath(ctx);
2384
+ CGContextFillPath(ctx);
2385
+ }
2386
+ } else if ([type isEqualToString:@"rect"]) {
2387
+ NSDictionary *p0 = (points && points.count > 0) ? points[0] : nil;
2388
+ NSDictionary *p1 = (points && points.count > 1) ? points[1] : p0;
2389
+ CGFloat x0 = [p0[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2390
+ CGFloat y0 = [p0[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2391
+ CGFloat x1 = [p1[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2392
+ CGFloat y1 = [p1[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2393
+ CGRect rect = CGRectMake(MIN(x0, x1), MIN(y0, y1), ABS(x1 - x0), ABS(y1 - y0));
2394
+ CGContextSetStrokeColorWithColor(ctx, strokeColor.CGColor);
2395
+ CGContextSetLineWidth(ctx, strokeWidth);
2396
+ CGContextStrokeRect(ctx, rect);
2397
+ } else if ([type isEqualToString:@"circle"] || [type isEqualToString:@"spotlight"]) {
2398
+ NSDictionary *p0 = (points && points.count > 0) ? points[0] : nil;
2399
+ NSDictionary *p1 = (points && points.count > 1) ? points[1] : p0;
2400
+ CGFloat x0 = [p0[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2401
+ CGFloat y0 = [p0[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2402
+ CGFloat x1 = [p1[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2403
+ CGFloat y1 = [p1[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2404
+ CGRect rect = CGRectMake(MIN(x0, x1), MIN(y0, y1), ABS(x1 - x0), ABS(y1 - y0));
2405
+ CGContextSetStrokeColorWithColor(ctx, strokeColor.CGColor);
2406
+ CGContextSetLineWidth(ctx, strokeWidth);
2407
+ CGContextStrokeEllipseInRect(ctx, rect);
2408
+ } else if ([type isEqualToString:@"step"]) {
2409
+ NSDictionary *p0 = (points && points.count > 0) ? points[0] : nil;
2410
+ CGFloat cx = [p0[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2411
+ CGFloat cy = [p0[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2412
+ CGFloat radius = 16.0 * baseScale;
2413
+ CGRect badgeRect = CGRectMake(cx - radius, cy - radius, radius * 2, radius * 2);
2414
+
2415
+ CGContextSetFillColorWithColor(ctx, strokeColor.CGColor);
2416
+ CGContextFillEllipseInRect(ctx, badgeRect);
2417
+
2418
+ CGContextSetStrokeColorWithColor(ctx, [UIColor whiteColor].CGColor);
2419
+ CGContextSetLineWidth(ctx, 2.0 * baseScale);
2420
+ CGContextStrokeEllipseInRect(ctx, badgeRect);
2421
+
2422
+ NSInteger stepNum = stroke[@"stepNumber"] ? [stroke[@"stepNumber"] integerValue] : 1;
2423
+ NSString *stepStr = [NSString stringWithFormat:@"%ld", (long)stepNum];
2424
+ UIFont *font = [UIFont boldSystemFontOfSize:14.0 * baseScale];
2425
+ NSDictionary *attrs = @{
2426
+ NSFontAttributeName: font,
2427
+ NSForegroundColorAttributeName: [UIColor whiteColor]
2428
+ };
2429
+ CGSize strSize = [stepStr sizeWithAttributes:attrs];
2430
+ CGPoint strOrigin = CGPointMake(cx - strSize.width / 2.0, cy - strSize.height / 2.0);
2431
+ [stepStr drawAtPoint:strOrigin withAttributes:attrs];
2432
+ }
2433
+ }
2434
+ }
2435
+
2436
+ // C. Draggable Text Badges / Notes
2437
+ if (texts && [texts isKindOfClass:[NSArray class]]) {
2438
+ for (NSDictionary *tItem in texts) {
2439
+ NSString *textStr = tItem[@"text"] ?: @"";
2440
+ if (textStr.length == 0) continue;
2441
+ BOOL isNorm = tItem[@"isNormalized"] ? [tItem[@"isNormalized"] boolValue] : YES;
2442
+ CGFloat tx = [tItem[@"x"] doubleValue] * (isNorm ? canvasW : 1.0);
2443
+ CGFloat ty = [tItem[@"y"] doubleValue] * (isNorm ? canvasH : 1.0);
2444
+ NSString *textColorHex = tItem[@"color"] ?: @"#FFFFFF";
2445
+ NSString *bgColorHex = tItem[@"bgColor"] ?: @"#EF4444";
2446
+ UIColor *textColor = inspectorColorFromHex(textColorHex, [UIColor whiteColor]);
2447
+ UIColor *bgColor = inspectorColorFromHex(bgColorHex, [UIColor redColor]);
2448
+
2449
+ UIFont *font = [UIFont boldSystemFontOfSize:15.0 * baseScale];
2450
+ NSDictionary *attrs = @{
2451
+ NSFontAttributeName: font,
2452
+ NSForegroundColorAttributeName: textColor
2453
+ };
2454
+ CGSize strSize = [textStr sizeWithAttributes:attrs];
2455
+ CGFloat padH = 12.0 * baseScale;
2456
+ CGFloat padV = 6.0 * baseScale;
2457
+ CGRect pillRect = CGRectMake(tx, ty, strSize.width + padH * 2.0, strSize.height + padV * 2.0);
2458
+ UIBezierPath *roundedPill = [UIBezierPath bezierPathWithRoundedRect:pillRect cornerRadius:pillRect.size.height / 2.0];
2459
+
2460
+ CGContextSetFillColorWithColor(ctx, bgColor.CGColor);
2461
+ CGContextAddPath(ctx, roundedPill.CGPath);
2462
+ CGContextFillPath(ctx);
2463
+
2464
+ CGContextSetStrokeColorWithColor(ctx, [[UIColor whiteColor] colorWithAlphaComponent:0.4].CGColor);
2465
+ CGContextSetLineWidth(ctx, 1.5 * baseScale);
2466
+ CGContextAddPath(ctx, roundedPill.CGPath);
2467
+ CGContextStrokePath(ctx);
2468
+
2469
+ [textStr drawAtPoint:CGPointMake(tx + padH, ty + padV) withAttributes:attrs];
2470
+ }
2471
+ }
2472
+
2473
+ // D. Legacy / Standalone Annotations
2474
+ if (annotations && [annotations isKindOfClass:[NSArray class]] && (!drawings || drawings.count == 0)) {
2276
2475
  for (NSDictionary *ann in annotations) {
2277
2476
  CGFloat x = [ann[@"x"] doubleValue];
2278
2477
  CGFloat y = [ann[@"y"] doubleValue];
@@ -2280,14 +2479,32 @@ RCT_EXPORT_METHOD(editPhoto:(NSDictionary *)options
2280
2479
  CGFloat h = [ann[@"height"] doubleValue];
2281
2480
  BOOL isNorm = [ann[@"isNormalized"] boolValue];
2282
2481
  if (isNorm) {
2283
- x *= resultImage.size.width;
2284
- y *= resultImage.size.height;
2285
- w *= resultImage.size.width;
2286
- h *= resultImage.size.height;
2482
+ x *= canvasW;
2483
+ y *= canvasH;
2484
+ w *= canvasW;
2485
+ h *= canvasH;
2287
2486
  }
2288
- CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
2289
- CGContextSetLineWidth(ctx, 4.0);
2487
+ NSString *annColorHex = ann[@"color"] ?: @"#EF4444";
2488
+ UIColor *annColor = inspectorColorFromHex(annColorHex, [UIColor redColor]);
2489
+ CGContextSetStrokeColorWithColor(ctx, annColor.CGColor);
2490
+ CGContextSetLineWidth(ctx, 4.0 * baseScale);
2290
2491
  CGContextStrokeRect(ctx, CGRectMake(x, y, w, h));
2492
+
2493
+ NSString *label = ann[@"label"];
2494
+ if (label && [label isKindOfClass:[NSString class]] && label.length > 0) {
2495
+ UIFont *font = [UIFont boldSystemFontOfSize:13.0 * baseScale];
2496
+ NSDictionary *attrs = @{
2497
+ NSFontAttributeName: font,
2498
+ NSForegroundColorAttributeName: [UIColor whiteColor]
2499
+ };
2500
+ CGSize strSize = [label sizeWithAttributes:attrs];
2501
+ CGFloat padH = 6.0 * baseScale;
2502
+ CGFloat padV = 3.0 * baseScale;
2503
+ CGRect tagRect = CGRectMake(x, MAX(0, y - strSize.height - padV * 2.0), strSize.width + padH * 2.0, strSize.height + padV * 2.0);
2504
+ CGContextSetFillColorWithColor(ctx, annColor.CGColor);
2505
+ CGContextFillRect(ctx, tagRect);
2506
+ [label drawAtPoint:CGPointMake(tagRect.origin.x + padH, tagRect.origin.y + padV) withAttributes:attrs];
2507
+ }
2291
2508
  }
2292
2509
  }
2293
2510
 
@@ -2516,74 +2733,31 @@ RCT_EXPORT_METHOD(pickMedia:(NSDictionary *)options
2516
2733
  reject:(RCTPromiseRejectBlock)reject) {
2517
2734
  dispatch_async(dispatch_get_main_queue(), ^{
2518
2735
  NSString *mediaType = options[@"mediaType"] ?: @"any";
2519
-
2520
- UIWindow *keyWin = nil;
2521
- if (@available(iOS 13.0, *)) {
2522
- for (UIScene *scene in [UIApplication sharedApplication].connectedScenes) {
2523
- if (scene.activationState == UISceneActivationStateForegroundActive && [scene isKindOfClass:[UIWindowScene class]]) {
2524
- for (UIWindow *w in ((UIWindowScene *)scene).windows) {
2525
- if (w.isKeyWindow) {
2526
- keyWin = w;
2527
- break;
2528
- }
2529
- }
2530
- }
2531
- if (keyWin) break;
2532
- }
2533
- }
2534
- if (!keyWin) {
2535
- #pragma clang diagnostic push
2536
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
2537
- keyWin = [UIApplication sharedApplication].keyWindow ?: [UIApplication sharedApplication].windows.firstObject;
2538
- #pragma clang diagnostic pop
2539
- }
2540
-
2541
- UIViewController *rootVC = keyWin.rootViewController;
2542
- while (rootVC.presentedViewController) {
2543
- rootVC = rootVC.presentedViewController;
2736
+ UIViewController *rootVC = GetTopViewController();
2737
+ if (!rootVC) {
2738
+ reject(@"PICK_ERROR", @"Unable to find active view controller for media picker", nil);
2739
+ return;
2544
2740
  }
2545
-
2741
+
2546
2742
  g_pickerDelegate = [[InAppInspectorPickerDelegate alloc] init];
2547
2743
  g_pickerDelegate.resolve = resolve;
2548
2744
  g_pickerDelegate.reject = reject;
2549
2745
  g_pickerDelegate.capturesDirectory = [self getCapturesDirectory];
2550
-
2551
- Class PHPickerVCClass = NSClassFromString(@"PHPickerViewController");
2552
- Class PHPickerConfigClass = NSClassFromString(@"PHPickerConfiguration");
2553
- Class PHPickerFilterClass = NSClassFromString(@"PHPickerFilter");
2554
-
2555
- if (PHPickerVCClass && PHPickerConfigClass && PHPickerFilterClass) {
2556
- id config = [[PHPickerConfigClass alloc] init];
2557
- [config setValue:@1 forKey:@"selectionLimit"];
2558
-
2559
- id filter = nil;
2560
- SEL imgFilterSel = NSSelectorFromString(@"imagesFilter");
2561
- SEL vidFilterSel = NSSelectorFromString(@"videosFilter");
2562
- SEL anyFilterSel = NSSelectorFromString(@"anyFilterMatchingSubfilters:");
2563
-
2746
+
2747
+ if (@available(iOS 14.0, *)) {
2748
+ PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
2749
+ config.selectionLimit = 1;
2750
+
2564
2751
  if ([mediaType isEqualToString:@"image"]) {
2565
- if ([PHPickerFilterClass respondsToSelector:imgFilterSel]) {
2566
- filter = ((id (*)(id, SEL))objc_msgSend)(PHPickerFilterClass, imgFilterSel);
2567
- }
2752
+ config.filter = [PHPickerFilter imagesFilter];
2568
2753
  } else if ([mediaType isEqualToString:@"video"]) {
2569
- if ([PHPickerFilterClass respondsToSelector:vidFilterSel]) {
2570
- filter = ((id (*)(id, SEL))objc_msgSend)(PHPickerFilterClass, vidFilterSel);
2571
- }
2754
+ config.filter = [PHPickerFilter videosFilter];
2572
2755
  } else {
2573
- id imgFilter = [PHPickerFilterClass respondsToSelector:imgFilterSel] ? ((id (*)(id, SEL))objc_msgSend)(PHPickerFilterClass, imgFilterSel) : nil;
2574
- id vidFilter = [PHPickerFilterClass respondsToSelector:vidFilterSel] ? ((id (*)(id, SEL))objc_msgSend)(PHPickerFilterClass, vidFilterSel) : nil;
2575
- if (imgFilter && vidFilter && [PHPickerFilterClass respondsToSelector:anyFilterSel]) {
2576
- filter = ((id (*)(id, SEL, id))objc_msgSend)(PHPickerFilterClass, anyFilterSel, @[imgFilter, vidFilter]);
2577
- }
2578
- }
2579
- if (filter) {
2580
- [config setValue:filter forKey:@"filter"];
2756
+ config.filter = [PHPickerFilter anyFilterMatchingSubfilters:@[[PHPickerFilter imagesFilter], [PHPickerFilter videosFilter]]];
2581
2757
  }
2582
-
2583
- SEL initConfigSel = NSSelectorFromString(@"initWithConfiguration:");
2584
- id rawPicker = [PHPickerVCClass alloc];
2585
- UIViewController *picker = ((UIViewController * (*)(id, SEL, id))objc_msgSend)(rawPicker, initConfigSel, config);
2586
- [picker setValue:g_pickerDelegate forKey:@"delegate"];
2758
+
2759
+ PHPickerViewController *picker = [[PHPickerViewController alloc] initWithConfiguration:config];
2760
+ picker.delegate = g_pickerDelegate;
2587
2761
  [rootVC presentViewController:picker animated:YES completion:nil];
2588
2762
  } else {
2589
2763
  UIImagePickerController *picker = [[UIImagePickerController alloc] init];
@@ -2603,6 +2777,93 @@ RCT_EXPORT_METHOD(pickMedia:(NSDictionary *)options
2603
2777
  });
2604
2778
  }
2605
2779
 
2780
+ RCT_EXPORT_METHOD(writeExportFile:(NSString *)filename
2781
+ content:(NSString *)content
2782
+ resolve:(RCTPromiseResolveBlock)resolve
2783
+ reject:(RCTPromiseRejectBlock)reject) {
2784
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
2785
+ @try {
2786
+ if (!filename || filename.length == 0) {
2787
+ reject(@"INVALID_FILENAME", @"Filename is missing", nil);
2788
+ return;
2789
+ }
2790
+ NSString *dir = [self getCapturesDirectory];
2791
+ NSString *cleanFilename = [filename lastPathComponent];
2792
+ NSString *outPath = [dir stringByAppendingPathComponent:cleanFilename];
2793
+ NSData *data = [(content ?: @"") dataUsingEncoding:NSUTF8StringEncoding];
2794
+ BOOL success = [data writeToFile:outPath atomically:YES];
2795
+ if (success) {
2796
+ resolve([NSURL fileURLWithPath:outPath].absoluteString);
2797
+ } else {
2798
+ reject(@"WRITE_FAILED", @"Failed to write export file", nil);
2799
+ }
2800
+ } @catch (NSException *e) {
2801
+ reject(@"WRITE_ERROR", e.reason, nil);
2802
+ }
2803
+ });
2804
+ }
2805
+
2806
+ RCT_EXPORT_METHOD(shareFile:(NSString *)filePath
2807
+ mimeType:(NSString *)mimeType
2808
+ title:(NSString *)title
2809
+ resolve:(RCTPromiseResolveBlock)resolve
2810
+ reject:(RCTPromiseRejectBlock)reject) {
2811
+ dispatch_async(dispatch_get_main_queue(), ^{
2812
+ @try {
2813
+ NSString *cleanPath = filePath;
2814
+ if ([cleanPath hasPrefix:@"file://"]) {
2815
+ cleanPath = [cleanPath substringFromIndex:7];
2816
+ }
2817
+ cleanPath = [cleanPath stringByRemovingPercentEncoding];
2818
+ if (![[NSFileManager defaultManager] fileExistsAtPath:cleanPath]) {
2819
+ reject(@"FILE_NOT_FOUND", @"File not found", nil);
2820
+ return;
2821
+ }
2822
+ NSURL *fileUrl = [NSURL fileURLWithPath:cleanPath];
2823
+ UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[fileUrl] applicationActivities:nil];
2824
+ if (title && title.length > 0) {
2825
+ [activityVC setValue:title forKey:@"subject"];
2826
+ }
2827
+ UIViewController *rootVC = GetTopViewController();
2828
+ if (!rootVC) {
2829
+ reject(@"SHARE_ERROR", @"Unable to find active view controller to share file", nil);
2830
+ return;
2831
+ }
2832
+ if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad && rootVC.view) {
2833
+ activityVC.popoverPresentationController.sourceView = rootVC.view;
2834
+ activityVC.popoverPresentationController.sourceRect = CGRectMake(CGRectGetMidX(rootVC.view.bounds), CGRectGetMidY(rootVC.view.bounds), 1, 1);
2835
+ activityVC.popoverPresentationController.permittedArrowDirections = 0;
2836
+ }
2837
+ activityVC.completionWithItemsHandler = ^(UIActivityType activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
2838
+ resolve(@(completed));
2839
+ };
2840
+ [rootVC presentViewController:activityVC animated:YES completion:nil];
2841
+ } @catch (NSException *e) {
2842
+ reject(@"SHARE_ERROR", e.reason, nil);
2843
+ }
2844
+ });
2845
+ }
2846
+
2847
+ - (void)invalidate {
2848
+ [super invalidate];
2849
+ hasListeners = NO;
2850
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
2851
+
2852
+ dispatch_async(dispatch_get_main_queue(), ^{
2853
+ if (self->displayLink != nil) {
2854
+ [self->displayLink invalidate];
2855
+ self->displayLink = nil;
2856
+ }
2857
+ if (self->_softwareRecordingTimerSource) {
2858
+ dispatch_source_cancel(self->_softwareRecordingTimerSource);
2859
+ self->_softwareRecordingTimerSource = nil;
2860
+ }
2861
+ if (floatingButtonView != nil) {
2862
+ [floatingButtonView removeFromSuperview];
2863
+ floatingButtonView = nil;
2864
+ }
2865
+ });
2866
+ }
2606
2867
 
2607
2868
  #ifdef RCT_NEW_ARCH_ENABLED
2608
2869
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule: